这道题很早之前就用数位dp做过一遍,但是那时候并没有理解透彻。今天又细细思考了一下,感觉比之前要好多了
题意:
就是叫你在[n,m]这个区间范围内找出不包含4和62的数字的个数。
思路:
1)暴力
2)数位dp:
做数位dp前,我们首先需要初始化,我们定义f[i][j]为开头为j的i位数中正常的数字有几个。
然后我们可以用三层for循环来对f数组进行初始化。
void init(){ f[0][0]=1;<span style="white-space:pre"> </span>//别忘记了 for(int i=1;i<=7;i++){ for(int j=0;j<=9;j++){ for(int k=0;k<=9;k++){ if((j!=4)&&(!(j==6&&k==2))){<span style="white-space:pre"> </span>//这里的逻辑关系一开始我写成||(j!=6&&k!=2),这样子是有问题的 f[i][j]=f[i-1][k]+f[i][j]; } } } } }
第一层我们for的是第几位,第二层我们则对第i位能够取到的数字进行枚举,第三层我们对第i-1位能够取到的数字进行枚举。因为当前第i位的取值关系只与第i-1位和当前第i位有关,所以我们就可以得到这个递推式了。
最重要的就是求数字有几个了。
今天我终于搞懂了为什么有时候是cal(m+1)-cal(n),而有时候是cal(m)-cal(n-1)了。
这个取决于你自己的dp是怎么定义的。当你定义为前i个数里面有多少个是符合条件的,那么就是我写的第一种写法。
如果定义为前i个数包括自己本身有多少个数是符合条件的,那么就是我写的第二种写法。
但是两种写法本质上并没有什么区别。
这道题我写的是第一种,即为不包含本身的。
求法为:
我们从低位到高位分别标记为1~n(n为位数),然后从高位开始寻找,然后后面代替的数字肯定不能大于当前那位的值,又因为我定义的是不包含自身,所以就得小于当前那位的值,然后ans+=已经求出来的f[i][j],就这样一位位的推下去,直至最后一位,所以这也就是我们最后一位为什么要加1的原因。
当然,当这位是4,或者这位是2并且前一位是6的情况下,那么直接跳出循环就好了。
int cal(int x){ int tmp=x,t=0; while(tmp){ dig[++t]=tmp%10; tmp=tmp/10; } dig[t+1]=0; int ans=0; for(int i=t;i>=1;i--){ for(int j=0;j<dig[i];j++){ if((j!=4)&&(!(j==2&&dig[i+1]==6))) ans+=f[i][j]; } if((dig[i]==4)||(dig[i]==2&&dig[i+1]==6)) break; } return ans; }
一开始我一直想不通为什么j循环到小于dig[i]就好了,其实就是定义的问题。
#include<stdio.h> #include<string.h> #include<queue> #include<map> #include<set> #include<queue> #include<stack> #include<math.h> #include<iostream> #include<algorithm> using namespace std; #define maxn 11 int dig[maxn]; int f[maxn][maxn]; void init(){ f[0][0]=1; for(int i=1;i<=7;i++){ for(int j=0;j<=9;j++){ for(int k=0;k<=9;k++){ if((j!=4)&&(!(j==6&&k==2))){ f[i][j]=f[i-1][k]+f[i][j]; } } } } } int cal(int x){ int tmp=x,t=0; while(tmp){ dig[++t]=tmp%10; tmp=tmp/10; } dig[t+1]=0; int ans=0; for(int i=t;i>=1;i--){ for(int j=0;j<dig[i];j++){ if((j!=4)&&(!(j==2&&dig[i+1]==6))) ans+=f[i][j]; } if((dig[i]==4)||(dig[i]==2&&dig[i+1]==6)) break; } return ans; } int main(){ int n,m; init(); while(~scanf("%d%d",&n,&m)){ if(n==0&&m==0) break; printf("%d\n",cal(m+1)-cal(n));<span style="white-space:pre"> </span>//!!! } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-12-25 20:08:47