【Ural1057】幂和的数量

【题目描述】

写一个程序来计算区间[X,Y]内满足如下条件的整数个数:它恰好等于K个互不相等的B的整数幂之和。

举个例子。令X=15,Y=20,K=2,B=2。在这个例子中,区间[15,20]内有3个整数恰好等于两个互不相等的2的整数幂之和:

17=2^4+2^0

18=2^4+2^1

20=2^4+2^2

【输入格式】

输入文件的第一行有两个空格隔开的整数X,Y(1<=X<=Y<=2^31-1).

第二行有两个整数K,B(1<=K<=20,2<=B<=10).

【输出格式】

输出一行一个整数,即[X,Y]中恰好等于K个互不相等的B的整数幂之和的数的个数。

【分析】

数位类统计,上一张图:

用f[i][j]来表示高度为i的二叉树下进制位有j个为1的数的个数。

对于询问n,我们需要求出不超过n的最大B进制表示只含0、1的数:
找到n 的左起第一位非0、1 的数位,将它变为1,并将右面所有数位设为1。(因为大于1的肯定不可取,后面置为1使它最接近原来的数)
将得到的B进制表示视为二进制进行询问即可。

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring> 
 4 int f[32][32];
 5 int x,y,k,b;
 6 
 7 int work(int x,int k);
 8 int change(int x);
 9 int main()
10 {
11     int i,j;
12     //初始化
13     f[0][0]=1;
14     for(i=1;i<=31;i++)
15     {
16         f[i][0]=f[i-1][0];
17         for(j=1;j<=i;j++)
18         f[i][j]=f[i-1][j]+f[i-1][j-1];
19     }
20     scanf("%d%d%d%d",&x,&y,&k,&b);
21     printf("%d
",work(change(y),k)-work(change(x-1),k));
22     return 0;
23 }
24 int change(int x)
25 {
26     int p=1,tot=0;
27     while(x>=(long long)p*b) p*=b,++tot;//用来统计有tot个b进制位 
28     int ans=0;
29     //b进制转2进制 
30     while(p && x/p<=1)
31     {
32           ans+=x/p*(1<<tot);
33           tot--;
34           x%=p;
35           p/=b;
36     }
37     ans+=(1<<(tot+1))-1;
38     return ans;
39 }
40 //统计[0..x]内二进制表示含k个1的数的个数
41 int work(int x,int k)
42 {
43     //tot记录当前路径上已有的1的数量
44     int ans=0,tot=0;
45     for(int i=31;i;i--)
46     {
47         if(x&(1<<i))
48         {
49             ++tot;
50             //跳出 
51             if(tot>k)break;
52             x^=(1<<i);
53         }
54         if((1<<(i-1))<=x)
55         ans+=f[i-1][k-tot];
56     }
57     if(x+tot==k)++ans;
58     return ans;
59 }
View Code
原文地址:https://www.cnblogs.com/hoskey/p/3721657.html