URAL 1057 Amount of Degrees (数位dp)
18 = 24+21,
20 = 24+22.
Input
2 ≤ B ≤ 10).
Output
Sample
Input
15 20
2 2
Output
3
所求的数为互不相等的幂之和,亦即其B 进制表示的各位数字都只能是0和1。因此,我们只需讨论二进制的情况,其他进制都可以转化为二进制求解。
很显然,数据范围较大,不可能采用枚举法,算法复杂度必须是log(n)级别,因此我们要从数位上下手。
本题区间满足区间减法,因此可以进一步简化问题:令count[i..j]表示[i..j]区间内合法数的个数,则count[i..j]=count[0..j]-count[0..i-1]。换句话说,给定n,我们只需求出从0 到n有多少个符合条件的数。
假设n=13,其二进制表示为1101,K=3。我们的目标是求出0 到13中二进制表示含3个1 的数的个数。为了方便思考,让我们画出一棵高度为4 的完全二叉树:
为了方便起见,树的根用0 表示。这样,这棵高度为4 的完全二叉树就可以表示所有4位二进制数(0..24-1),每一个叶子节点代表一个数。其中,红色路径表示n。所有小于n的
数组成了三棵子树,分别用蓝色、绿色、紫色表示。因此,统计小于13 的数,就只需统计这三棵完整的完全二叉树:统计蓝子树内含3 个1的数的个数、统计绿子树内含2 个1 的数的个数(因为从根到此处的路径上已经有1 个1),
以及统计紫子树内含1个1 的数的个数。
注意到,只要是高度相同的子树统计结果一定相同。而需要统计的子树都是“右转”时遇到的。当然,我们不能忘记统计n 本身。实际上,在算法最初时将n 自加1,可以避免讨论n
本身,但是需要注意防止上溢。剩下的问题就是,如何统计一棵高度为i的完全二叉树内二进制表示中恰好含有j个1的数的个数。这很容易用递推求出:设f[i,j]表示所求,则分别统计左右子树内符合条件数的个数
,有f[i,j]=f[i-1,j]+f[i-1,j-1]。
这样,我们就得出了询问的算法:首先预处理f,然后对于输入n,我们在假想的完全二叉树中,从根走到n所在的叶子,每次向右转时统计左子树内数的个数。
最后的问题就是如何处理非二进制。对于询问n,我们需要求出不超过n的最大B进制表示只含0、1的数:找到n 的左起第一位非0、1 的数位,将它变为1,并将右面所有数位设为1。将得到的B进制表示视为二进制进行询问即可。
代码如下:
#include <bits/stdc++.h> using namespace std;
int f[][],d[];
void init ()//其实这就是个杨辉三角形
{
memset(f,,sizeof f);
f[][]=;
for (int i=;i<=;++i)
{
f[i][]=;
for (int j=;j<=i;++j)
f[i][j]=f[i-][j-]+f[i-][j];
}
}
int calc (int x,int k)
{
int tot=,ans=;
for (int i=;i>;--i)
{
if (x&(<<i))//x的第i+1位是不是1
{
tot++;
//printf("i=%d tot=%d\n",i,tot);
if (tot>k)
break;
x^=(<<i);//把这位削成0
}
if (<<(i-)&x)//能否右转,能则统计左子树,即i-1位选0
{
//printf("i-1=%d tot=%d f=%d\n",i-1,tot,f[i-1][k-tot]);
ans+=f[i-][k-tot];
} }
if (tot+x==k)//如果全都是1,则没有统计,++ans补上
ans++;
//printf("ans=%d\n",ans);
return ans;
}
int transfer (int b,int x)//将x,y转换成等价的二进制数
{
int m=,ans=;
while (x)
{
d[m++]=x%b;
x/=b;
}
for (int i=m-;i>=;--i)
{
if (d[i]>)
{
for (int j=i;j>=;j--)
ans|=(<<j);
}
else
ans|=d[i]<<i;
}
return ans;
}
int main()
{
//freopen("de,txt","r",stdin);
long long int x,y;
int k,b;
init();
while (~scanf("%lld%lld",&x,&y))
{
scanf("%d %d",&k,&b);
x=transfer(b,x-);
y=transfer(b,y);
printf("%d\n",calc(y,k)-calc(x,k));
}
return ;
}
论文参照《浅谈数位类统计问题》 作者:山东省青岛第二中学 刘聪
URAL 1057 Amount of Degrees (数位dp)的更多相关文章
- URAL 1057. Amount of Degrees(数位DP)
题目链接 我看错题了...都是泪啊,不存在3*4^2这种情况...系数必须为1... #include <cstdio> #include <cstring> #include ...
- [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 am ...
- Ural 1057 Amount of Degrees
Description 问[L,R]中有多少能表示k个b次幂之和. Sol 数位DP. 当2进制时. 建出一个二叉树, \(f[i][j]\) 表示长度为 \(i\) 有 \(j\) 个1的个数. 递 ...
- Ural1057 - Amount of Degrees(数位DP)
题目大意 求给定区间[X,Y]中满足下列条件的整数个数:这个数恰好等于K个互不相等的B的整数次幂之和.例如,设X=15,Y=20,K=2,B=2,则有且仅有下列三个数满足题意: 输入:第一行包含两个整 ...
- ural 1057 Amount of degrees 【数位dp】
题意:求(x--y)区间转化为 c 进制 1 的个数为 k 的数的出现次数. 分析:发现其满足区间减法,所以能够求直接求0---x 的转化为 c 进制中 1 的个数为k的数的出现次数. 首先用一个数组 ...
- URAL 1057 Amount of Degrees (数位DP,入门)
题意: 求给定区间[X,Y]中满足下列条件的整数个数:这个数恰好等于K个互不相等的,B的整数次幂之和.例如,设X=15,Y=20,K=2,B=2,则有且仅有下列三个数满足了要求: 17 = 24+2 ...
- [ural1057][Amount of Degrees] (数位dp+进制模型)
Discription Create a code to determine the amount of integers, lying in the set [X; Y] and being a s ...
- Timus Online Judge 1057. Amount of Degrees(数位dp)
1057. Amount of Degrees Time limit: 1.0 second Memory limit: 64 MB Create a code to determine the am ...
- ural 1057Amount of Degrees ——数位DP
link:http://acm.timus.ru/problem.aspx?space=1&num=1057 论文: 浅谈数位类统计问题 刘聪 #include <iostream&g ...
随机推荐
- C++ string.replace的使用
//下面是一个检查一个字符串中是否有'.'的函数,该函数将找到的'.'转化为'_'. inline void checkName(string& name) { std::; while (s ...
- Dllregisterserver调用失败解决方法
在做一个注册com组件时,出现这样的情况 出现这个错误一般是和权限问题有关,命令提示符需要以管理员权限运行才可以注册成功. 最简单的解决方法就是: 在开始菜单右击—>命令提示符(管理员)(A) ...
- Sticks
题目链接 题意:给你一组等长木棒,然后他随意砍断成n个木棒,木棒长度不一,但你知道分别是多少,要你求出原始木棒可能的最小长度. 思路:首先那个原始木棒的长度肯定是其总长度的约数,然后也肯定大于等于所有 ...
- windows平台使用MongoDB shell 来连接 MongoDB 服务器并创建数据库
windows平台使用MongoDB shell 来连接 MongoDB 服务器并创建数据库 命令行进入MongoDB的bin目录运行mongod.exe mongod --dbpath c:\dat ...
- [CSP-S模拟测试]:english(可持久化Trie+启发式合并)
题目传送门(内部题24) 输入格式 第一行有$3$个整数$n,opt$,$opt$的意义将在输出格式中提到.第二行有$n$个整数,第$i$个整数表示$a_i$. 输出格式 若$opt=1$,输出一行一 ...
- SelfCert wcf中 生成x5.09证书的工具
http://blog.pluralsight.com/selfcert-create-a-self-signed-certificate-interactively-gui-or-programma ...
- css控制显示超出多少行以后开始出现省略号的写法
display: -webkit-box; display: -moz-box; text-overflow: -o-ellipsis-lastline; text-overflow: ellipsi ...
- MySQL 添加用户、删除用户与授权
mysql -uroot -proot MySQL5.7 mysql.user表没有password字段改 authentication_string: 一. 创建用户: 命令:CREATE USER ...
- js实现的页面加载完毕之前loading提示效果
页面加载readyState的五种状态 原文如下: 0: (Uninitialized) the send( ) method has not yet been invoked. 1: (Loadin ...
- 时间复杂度为n^2的排序
时间复杂度为n^2的排序 冒泡排序和选择排序的共同点:每次都是在找剩下元素中最小(大)的元素 不同点:冒泡排序存在多次交换,而选择排序每次只存在一次交换序号 #include<iostream& ...