数位动态规划(acm hdu 3555 ,hdu 2089,hdu 4278)
2016-08-04 09:33
387 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3555
题意:给定一个上界n,求在1-n中有多少个数含有49
题解:因为数值太大,考虑用数位dp,按照每一位进行考虑,对于每一位i考虑dp[i][0]:在i位时不含49的数,dp[i][1]:在i位时不含49的数中含第i位为9的数(只要考虑第i+1为4就可以凑出49),dp[i][2]在i位时累计含49的值的总和,其他见注释
代码:
题目:http://acm.split.hdu.edu.cn/showproblem.php?pid=2089
题意:给定区间,查找区间中部存在62或4的数的总数
题解:如上
代码:
题目:http://acm.split.hdu.edu.cn/showproblem.php?pid=4278
题意:一个仪表盘无法显示3和8,到2时下个数就会跳到4,同理7时就会自动跳到9,给点现在显示的数字,要求求出本来实际的值
题解:因为无法显示3和8,就是排除掉带3和8的所有数,同上原理也用数位dp
代码:
题意:给定一个上界n,求在1-n中有多少个数含有49
题解:因为数值太大,考虑用数位dp,按照每一位进行考虑,对于每一位i考虑dp[i][0]:在i位时不含49的数,dp[i][1]:在i位时不含49的数中含第i位为9的数(只要考虑第i+1为4就可以凑出49),dp[i][2]在i位时累计含49的值的总和,其他见注释
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; long long dp[22][3]; long long n; int d[22]; int main() { int t; scanf("%d",&t); dp[0][0]=1; for(int i=1;i<21;i++)//先提前计算dp值 { //考虑第i位取输入值小一位值的时候,第i-1位可以取0-9,那么dp[i][0]就为dp[i-1][0]*10再减去 //dp[i-1][1](i-1位为9,i位为4的情况) dp[i][0]=dp[i-1][0]*10-dp[i-1][1]; dp[i][1]=dp[i-1][0];//第i位为9的情况 dp[i][2]=dp[i-1][1]+dp[i-1][2]*10;//前面已有49,则第i位取任意值,或是上一位为9,此位为4的情况 } while(t--) { scanf("%lld",&n); n++; //以下算法没考虑n本身,要通过加1来考虑n本身 int cont=0; //分解每一位 while(n!=0) { d[++cont]=n%10; n/=10; } long long sum=0; int lastnumber=0,flag=0; for(int i=cont;i>=1;i--) { sum+=dp[i-1][2]*d[i];//考虑0-(d[i]-1)的情况,即考虑i位取0-(d[i]-1)时 //后i位可以任意取都不会超过原值 if(flag) {sum+=dp[i-1][0]*d[i];} //考虑高位已经存在了49的情况,即原输入的上界高位有49,那么后面可以任意取,只要保证不超界 if(!flag && d[i]>4){sum+=dp[i-1][1];} //考虑比i高位不存在49时,第i位可以取到4不越界的情况下,第i-1取9的情况 if(lastnumber==4&&d[i]==9){flag=1;} //当上一位为4,此位为9时,说明输入值高位已有49,即后位可取任意不超的值 lastnumber=d[i]; } cout<<sum<<endl; } return 0; }
题目:http://acm.split.hdu.edu.cn/showproblem.php?pid=2089
题意:给定区间,查找区间中部存在62或4的数的总数
题解:如上
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<queue> using namespace std; int dp[10][5]; void init() { dp[0][1]=0; dp[0][2]=1; dp[0][3]=0; for(int i=1;i<=7;i++) { dp[i][1]=10*dp[i-1][1]+dp[i-1][3]+dp[i-1][2]; dp[i][2]=9*dp[i-1][2]-dp[i-1][3]; dp[i][3]=dp[i-1][2]; } } int getNumber(int d) { int sum=0; int l[10]; int cnt=1; while(d!=0) { l[cnt++]=d%10; d/=10; } int last=0,flag=0; for(int i=cnt-1;i>=1;i--) { sum+=l[i]*dp[i-1][1]; if(flag) sum+=l[i]*dp[i-1][2]; if(!flag&&l[i]>4)sum+=dp[i-1][2]; if(!flag&&l[i]>6)sum+=dp[i-1][3]; if(!flag && last==6 && l[i]>2) sum+=dp[i][3]; if((last==6&&l[i]==2)||l[i]==4){flag=1;} last=l[i]; } return sum; } int main() { int l,r; init(); while(scanf("%d %d",&l,&r)!=EOF&&(l||r)) { int d1=getNumber(l); int d2=getNumber(r+1); printf("%d\n",r-d2-(l-d1)+1); } return 0; }
题目:http://acm.split.hdu.edu.cn/showproblem.php?pid=4278
题意:一个仪表盘无法显示3和8,到2时下个数就会跳到4,同理7时就会自动跳到9,给点现在显示的数字,要求求出本来实际的值
题解:因为无法显示3和8,就是排除掉带3和8的所有数,同上原理也用数位dp
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> using namespace std; long long dp[20][2]; void getNumber() { dp[0][1]=1; for(int i=1;i<=11;i++) { dp[i][0]=2*dp[i-1][1]+10*dp[i-1][0]; dp[i][1]=8*dp[i-1][1]; } } long long getCount(long long num) { int number[20]; int count1=0; long long sum=0; while(num) { number[count1++]=num%10; num/=10; } bool flag=false; for(int i=count1-1;i>=0;i--) { sum+=number[i]*dp[i][0]; if(!flag&&number[i]>3){sum+=dp[i][1];} if(!flag&&number[i]>8){sum+=dp[i][1];} if(flag){sum+=number[i]*dp[i][1];} if(number[i]==3||number[i]==8){flag=1;} } return sum; } int main() { long long number; getNumber(); while(~scanf("%lld",&number)&&number) { printf("%lld: %lld\n",number,number-getCount(number+1)); } return 0; }
相关文章推荐
- [置顶] 数位DP 51Nod1009,hdu 4278,2089,3652,3555,4507,poj 3252
- 数位DP入门题 hdu 2089 hdu 3555
- hdu 2089 & hdu 3555 (数位DP)
- HDU 3555 Bomb ,HDU 2089 深刻学习数位dp (各种方法乱用)
- 几个基础数位DP(hdu 2089,hdu 3555,uestc 1307 windy 数)
- hdu 2089 不要62 hdu 3555 Bomb (数位DP)
- 【数位dp】hud 2089 不要62 hdu 3555 Bomb
- 动态规划晋级——HDU 3555 Bomb【数位DP详解】
- HDU 3555 Bomb + HDU 2089 不要62 数位dp入门题目
- 几个基础数位DP (hdu 2089,hdu 3555 ,uestc 1307 windy 数)
- HDU 2089 不要62 && HDU 3555 Bomb (数位DP)
- 几个基础数位DP (hdu 2089,hdu 3555 ,uestc 1307 windy 数)
- HDU 2089 & HDU 3555 数位dp
- HDU 3555 Bomb [数位DP]【动态规划】
- HDU 3555 浅谈数位动态规划逆向计数问题练习
- 【数位dp】【HDU 3555】【HDU 2089】数位DP入门题
- [HDU - 2089] 不要62 (动态规划 && 数位dp)
- hdu 3555 Bomb (数位dp)
- HDU 2089 不要62 (数位dp入门题)
- hdu 2089 -不要62(数位 dp)