hdu 4722 Good numbers(数位DP)
2015-12-29 09:20
676 查看
题目: http://acm.hdu.edu.cn/showproblem.php?pid=4722
输出从a到b的所有数字满足所有位数数字之和能被10整除的个数。
第一次做有关数位DP的题。开始真不懂,看了别人的代码也没立刻懂。特别是那神奇的一块代码:
自己写一遍理解了些许,bit[20]存储十进制位数,dp[i][j]代表长度是i的数字所有位上数字之和%10得到的余数j的个数,简单例子:
对于23,比第一位数字小的有j=0,j=1,先计算上,dp[1][j]++(x=0),然后将2记录下来,第一位处理完毕
比第二位数字小的有j=0,j=1,j=2,dp[2][j+x]++。长度更长的数字下一位原则上是什么数字(0--9)都存在可能,所以所有的dp[i][余数]都加上前者的个数
一个中间过程:
4
0 23
b=23
1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0
2 2 3 3 3 2 2 2 2 2
a-1=-1
out:2
的交换输出的是0。当然,如果是:
也是可以的。
哎,还有很多的东西要学习。。。
输出从a到b的所有数字满足所有位数数字之和能被10整除的个数。
第一次做有关数位DP的题。开始真不懂,看了别人的代码也没立刻懂。特别是那神奇的一块代码:
for(int i=1;i<=cnt;i++){ for(int j=0;j<10;j++){ for(int k=0;k<10;k++){ dp[i][(j+k)%10]+=dp[i-1][j]; } } for(int j=0;j<bit[i];j++){ dp[i][(j+x)%10]++; } x=(x+bit[i])%10; }
自己写一遍理解了些许,bit[20]存储十进制位数,dp[i][j]代表长度是i的数字所有位上数字之和%10得到的余数j的个数,简单例子:
对于23,比第一位数字小的有j=0,j=1,先计算上,dp[1][j]++(x=0),然后将2记录下来,第一位处理完毕
比第二位数字小的有j=0,j=1,j=2,dp[2][j+x]++。长度更长的数字下一位原则上是什么数字(0--9)都存在可能,所以所有的dp[i][余数]都加上前者的个数
一个中间过程:
4
0 23
b=23
1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0
2 2 3 3 3 2 2 2 2 2
a-1=-1
out:2
#include <iostream> #include <cstring> #include <cstdio> using namespace std; typedef long long LL; LL bit[20],dp[20][10]; //dp: 长度i的数字数位求和余数是j的数字个数 int cnt; LL work(LL n){ if(n<0) return 0; LL temp=n; cnt=0; memset(dp,0,sizeof(dp)); while(temp){ bit[++cnt]=temp%10; temp/=10; } for(int i=1;i<=cnt/2;/*cnt-i+1>=i;*/ i++){ //交换 高低位互换 bit[i]=bit[i]^bit[cnt-i+1]; bit[cnt-i+1]=bit[i]^bit[cnt-i+1]; bit[i]=bit[i]^bit[cnt-i+1]; } int x=0; for(int i=1;i<=cnt;i++){ for(int j=0;j<10;j++){ for(int k=0;k<10;k++){ //向后堆积 下一低位0——9均有可能 dp[i][(j+k)%10]+=dp[i-1][j]; } } for(int j=0;j<bit[i];j++){ dp[i][(j+x)%10]++; //计算余数 (不含当前位) } x=(x+bit[i])%10; //处理当前位 } if(x==0) dp[cnt][0]++; return dp[cnt][0]; } int main() { //freopen("cin.txt","r",stdin); int t,ca=0; LL a,b; cin>>t; while(t--){ scanf("%I64d%I64d",&a,&b); printf("Case #%d: %I64d\n",++ca,work(b)-work(a-1)); } return 0; }还发现一个问题,如果用异或交换两个数,那么那个bit[]代码里for的限制条件应该是i<=cnt/2,因为cnt-i+1>=i会使得数字自己交换自己,而l类似于:
int a=10; a=a^a; a=a^a; a=a^a;
的交换输出的是0。当然,如果是:
for(int i=1;cnt-i+1>=i;i++){ //交换 高低位互换 int t=bit[i]; bit[i]=bit[cnt-i+1]; bit[cnt-i+1]=t; }
也是可以的。
哎,还有很多的东西要学习。。。
相关文章推荐
- 打造atom成为golang开发神器
- django修改admin下编辑的控件形式
- Go Reflect
- 使用golang开发websocket的记录
- Django后台管理
- GoldenGate 12.2 支持不可见列invisible column的复制
- Union-find
- goal
- Google gflags介绍
- MVC使用Google OAuth[OWIN]注意事項
- 怎样用Google APIs和Google的应用系统进行集成(1)----Google APIs简介
- 如何进入google
- django 常用命令汇总 - - note
- Django学习笔记2
- AS2.0大步更新 Google强势逆天
- Django学习笔记1
- Lind.DDD.Repositories.Mongo层介绍
- 启动带两个category值得预定义activity和桌面activity
- 关于mongoldb 启动时显示 add already in use
- 占坑抽空补题解>_< 【杭电2015年12月校赛B】【计算几何】 Polygon 求直线和多边形的交线长度