poj 3286 How many 0's? (数位DP+ 统计)
来源:互联网 发布:网络打鱼能赢吗 编辑:程序博客网 时间:2024/06/03 13:29
题意 :计算 m到n区间中的数一共包含了多少个0.
思路:定义DP状态dp[a][b][c]表示a位数,开头为b ,含有c个0的数的个数。
转移状态:
if(b>=1)
dp[a][b][c]+=dp[a-1][z][c] (0=<z<=9)
else
dp[a][b][c]+=dp[a-1][z][c-1] (0=<z<=9)
对数字进行DP预处理,然后对于每个低于n或m的数字进行去除前导0的特殊处理,最后特判m即可。
本题WA在了两个地方 :
1、1000-1050 这里面如果直接算小于第三位数字的数那就直接跳过了,但实际上要记录,下一位往后的数字大小等量的0.
2、0 0这种情况要进行特判。
3、因为无符号整型,所以要用long long 。
#include <iostream>#include <cstdio>#include <cstring>typedef long long LL;using namespace std;LL dp[22][12][22];int len[3];int num[3][22];LL bit[19];//预处理10的几次方LL nn[19];//处理m的i位往后数字组成的数是多少LL nn1[19];//处理n的i位往后的数字组成的数是多少LL m,n;void work(){ dp[0][0][0]=1; for(int i=1; i<=20; i++) { for(int j=0; j<=9; j++) for(int k=0; k<=i; k++) { for(int z=0; z<=9; z++) { if(j>=1) { dp[i][j][k]+=dp[i-1][z][k]; } else { // if(k>=1) dp[i][j][k]+=dp[i-1][z][k-1]; } } } }}void cal(int t){ len[t]=0; if(t==0) { while(m) { //cout<<m<<endl; num[t][++len[t]]=m%10; nn[len[t]]=nn[len[t]-1]+num[t][len[t]]*bit[len[t]]; m/=10; } } else { while(n) { num[t][++len[t]]=n%10; nn1[len[t]]=nn1[len[t]-1]+num[t][len[t]]*bit[len[t]]; n/=10; } }}LL solve(){ LL res=0; LL sum=0; for(int i=len[0]; i>0; i--) { if(num[0][i]!=0) { res+=(nn[i])*sum; sum=0; } else { sum++; } for(int j=0; j<num[0][i]; j++) { if((j==0)&&(i==len[0])) continue; for(int l=0; l<=i; l++) { res+=(LL)dp[i][j][l]*l; } } } for(int i=len[0]-1; i>0; i--) { for(int j=1; j<=9; j++) { for(int z=0; z<i; z++) { res+=(LL)dp[i][j][z]*z; } } } LL res1=0; LL sum1=0; for(int i=len[1]; i>0; i--) { if(num[1][i]!=0) { res1+=(nn1[i])*sum1;//这里处理1050这种情况 sum1=0; } else { sum1++; } for(int j=0; j<num[1][i]; j++) { if((j==0)&&(i==len[1])) continue; for(int l=0; l<=i; l++) { res1+=(LL)dp[i][j][l]*l; } } } for(int i=len[1]-1; i>0; i--)//特殊处理小于len的 { for(int j=1; j<=9; j++) { for(int z=0; z<i; z++) { res1+=(LL)dp[i][j][z]*z; } } } return res1-res;}LL check(){ LL cnt=0; for(int i=1; i<=len[1]; i++) { if(num[1][i]==0) { cnt++; } } return cnt;}int main(){ freopen("in.txt","r",stdin); memset(dp,0,sizeof(dp)); memset(num,0,sizeof(num)); memset(nn,0,sizeof(nn)); memset(nn1,0,sizeof(nn1)); work(); bit[1]=1; for(int i=2;i<=17;i++) { bit[i]=bit[i-1]*10; } while(~scanf("%lld%lld",&m,&n)) { LL ans1=0; if((m==0)&&(n==0)) { printf("1\n"); continue; } if((m==-1)) break; if(m==0) { num[0][1]=0; len[0]=1; ans1++; } else { cal(0); } cal(1); ans1+=solve()+check(); printf("%lld\n",ans1); } return 0;}
- poj 3286 How many 0's? (数位DP+ 统计)
- poj 3286 How many 0's? --- 数位dp
- How many 0's? - POJ 3286 数位dp
- POJ 3286 How many 0's?(数位DP)
- POJ 3286 How many 0's? (数位dp)
- POJ 3286 How many 0's?(数位dp)
- POJ - 3286 - How many 0s? 【数位DP】
- poj 3286 How many 0's? 数位dp
- poj 2282 The Counting Problem && poj 3286 How many 0's? (数位dp)
- Poj 3286 How many 0's? + Bzoj 1833 count 数字计数(数位统计)
- POJ3286:How many 0's?(数位DP)
- 数位dp poj3286 How many 0's?
- poj 3286 How many 0's? 按位统计
- poj3286--How many 0's?(数位dp)
- poj3286 How many 0's? (数位DP)
- uva11038 How Many O's? 数位dp
- poj 3286 How many 0's?
- POJ 3286How many 0's?
- [机器学习] PCA理论
- ASP利用IP138获IP地理位置
- top命令学习笔记
- session的属性设置
- Factorials
- poj 3286 How many 0's? (数位DP+ 统计)
- Bootstrap+Timeliner+Github+JQUERY创建程序员的简历(二)---专业技能表
- 系统时间同步到互联网时间
- Documentation/block/stat
- CPP_Primer CH6--抽象容器
- 各种工具类
- 新键用户到管理员组
- ckeditor4.2.2插件应用
- 新的开始吧