【Ural 1057】幂和的数量

【题目描述】


写一个程序来计算区间[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\n",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 }

【Ural 1057】幂和的数量

时间: 2024-12-28 00:57:56

【Ural 1057】幂和的数量的相关文章

URAL - 1057 Amount of Degrees

Description Create a code to determine the amount of integers, lying in the set [ X; Y] and being a sum of exactly K different integer degrees of B. Example. Let X=15, Y=20, K=2, B=2. By this example 3 numbers are the sum of exactly two integer degre

URAL 1057 Amount of Degrees(数位统计)

题意:  求给定区间[X,Y]中满足下列条件的整数个数:这个数恰好等于K 个互不相等的B的整 数次幂之和. 思路:对于二进制来说(图片摘自刘聪的浅谈数位类统计问题论文) 现在推广到b进制 因为对于b进制的每一位,我们只需要讨论这一位是否是一,所以我们可以把这个数转换为一个等价的二进制数, 方法是将这个数从左到右第一位不是零或一的位变为1,并把其右边的所有位置一,求出这个二进制数. #include<cstdio> #include<cstring> #include<cm

URAL 1057 Amount of Degrees (数位DP,入门)

题意: 求给定区间[X,Y]中满足下列条件的整数个数:这个数恰好等于K个互不相等的,B的整数次幂之和.例如,设X=15,Y=20,K=2,B=2,则有且仅有下列三个数满足了要求:  17 = 24+20, 18 = 24+21, 20 = 24+22.(以B为底数,幂次数不允许相同) 参考论文-->>论文中的题. 思路: 论文倒是容易看明白,但是这个转成B进制的思想一直转不过来.其实转成B进制后变成 a1*Bn+a2*Bn-1...an*B0.其中ai是系数.范围是[0,B-1].但是看了论文

[ACM] ural 1057 Amount of degrees (数位统计)

1057. Amount of Degrees Time limit: 1.0 second Memory limit: 64 MB Create a code to determine the amount of integers, lying in the set [X;Y] and being a sum of exactlyK different integer degrees of B. Example. Let X=15, Y=20, K=2, B=2. By this exampl

Ural 1057 Amount of Degrees(数位DP)

题目链接:点击打开链接 题目大意:求给定区间[X,Y]中满足下列条件的整数个数:这个数恰好等于K个互不相等的B的整数次幂之和.例如,设X=15,Y=20,K=2,B=2,则有且仅有下列三个数满足题意:17 = 2^4+2^0, 18 = 2^4+2^1, 20 = 2^4+2^2. 1 ≤ X ≤ Y ≤ 2^31?1,1 ≤ K ≤ 20,  2 ≤ B ≤ 10. 思路:数位DP的思想, 因为本题满足区间减法, 所以我们只需要求出一个不大于n的满足要求的数的个数,那么先预处理出一个B进制数列

ural 1057 Amount of degrees 【数位dp】

题意:求(x--y)区间转化为 c 进制 1 的个数为 k 的数的出现次数. 分析:发现其满足区间减法,所以可以求直接求0---x 的转化为 c 进制中 1 的个数为k的数的出现次数. 首先用一个数组f[i][j]:表示前 i 位中有 j 位为 1 的个数. 可以通过方程 f[i][j] = f[i-1][j] + f[i-1][j-1]来预处理出来. 对于要求的答案,我们可以借助树来求. 假如13 ,2进制,有3个1 ,转化为2进制 1101 可以借助于一个二进制的表示的树来求. AC代码:

ural 1057. Amount of Degrees 数位dp

题目链接 给四个数l, r, k, b. 求出在[l, r]内满足这个数可以分解成k个不同的b次方的数的个数. 只要把一个数按b进制分解, 然后找一个刚好有k个1, 其余都是0的数的个数. 好神....按B进制分解完全想不到. 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define pb(x) push_back(x) 4 #define ll long long 5 #define mk(x, y) make_pair(x, y)

[数位dp] ural 1057 Amount of Degrees

题意:x.y.k.b.在[x,y]范围内的b进制数能分成k个b进制位权和的数有多少个. 思路: dp[site][n][k][b] n就代表已经分成了几个. 其实就是把数转换成对应的进制 然后这时候len不再是原来的那么简单. 应该是如果是边界的话取  当前位和1的最小值 不是的话 就取1 因为这位上有数说明这位可以被分走 所以这位上的数多少他都是1 然后就是判断是否是边界 要判断到是不是等于这个位上的数 而不是等于len. 代码: #include"cstdlib" #include

ural 1057 Amount of degrees 题解

题目大意:统计区间[x,y]中在b进制下含k个1的数字个数. 数位dp. 具体见2009刘聪论文<浅谈数位类统计问题>... 1 #include<cstdio> 2 const int MAXN=32; 3 int f[MAXN][MAXN]; 4 void init() 5 { 6 f[0][0]=1; 7 for(int i=1;i<MAXN;++i) 8 { 9 f[i][0]=f[i-1][0]; 10 for(int j=1;j<=i;++j) 11 f[i