国家队论文首题 浅谈数位类统计问题 ural 1057

看《浅谈数位类统计问题》论文写的,感觉分析还是相当的到位啊。

一个数分解成进制数相加,该位置上的数绝对为1.

代码:

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 using std::min;
 6 using std::swap;
 7 int const N = 40;
 8 int f[N][N],num[N],top,x,y,b,k,s,tot;
 9 void pre()
10 {
11      f[0][0]=1;
12      for(int i=1;i<=31;i++)
13      {
14          f[i][0]=f[i-1][0];
15          for(int j=1;j<=i;j++)
16          f[i][j]=f[i-1][j]+f[i-1][j-1];
17      }
18 }
19 int getsum(int x,int b)
20 {
21     tot=s=top=0;
22     while(x)
23     {
24           num[top++]=x%b;
25           x/=b;
26     }
27     for(int i=top-1;i>=0;i--)
28     {
29         if(!s&&num[i]>0)s=i;
30         if(num[i]>1)
31         {
32            while(i>=0)x^=(1<<i),i--;
33            break;
34         }
35         if(num[i]==1)
36         {
37            x^=(1<<i);
38         }
39     }
40     int ret=0;
41     s++;
42     s=min(31,s);
43     for(;s>0;s--)
44     {
45         if(x&(1<<s))
46         {
47            tot++;
48            if(tot>k)break;
49            x^=(1<<s);
50         }
51         if((1<<(s-1))<=x)
52         {
53            ret+=f[s-1][k-tot];
54         }
55     }
56     if(tot+x==k)ret++;
57     return ret;
58 }
59 int main()
60 {
61     pre();
62     while(~scanf("%d %d %d %d",&x,&y,&k,&b))
63     {
64           if(x>y)swap(x,y);
65           printf("%d\n",getsum(y,b)-getsum(x-1,b));
66     }
67     return 0;
68 }
原文地址:https://www.cnblogs.com/nuoyan2010/p/3042180.html