题意:求[n,m]内所有数字中不出现4也不出现连续62的数的个数。
输入:n m,多组数据,以0 0结尾。
输出:符合条件的数的个数。
限制:(0<n≤m<1000000) 时间:1000 ms 空间:32768 kB
分析:我们引入数位DP的应用范围:求出在给定区间[A,B]内,符合条件P(i)的数i的个数.条件P(i)一般与数的大小无关,而与 数的组成 有关.
本题我们采用打表+递推的DP思路解题,空间复杂度比记忆化搜索略高,但便于理解。
#include <cstring> #include <cstdio> int dp[10][10];//dp[i][j]表示第i位为j时符合条件的数的个数 void init(){//打表 memset(dp,0,sizeof(dp)); dp[0][0]=1; for(int i=1;i<=7;i++) for(int j=0;j<10;j++)//枚举第i位可能出现的数 for(int k=0;k<10;k++)//枚举第i-1位可能出现的数 if(j!=4&&!(j==6&&k==2)) dp[i][j]+=dp[i-1][k]; } int solve(int n){ //printf("%d********%d*********%d\n",dp[4][2],dp[5][6],dp[5][7]); int digit[10],len=0,ans=0; while(n>0){ digit[++len]=n%10; n/=10; } digit[len+1]=0; for(int i=len;i;i--){//从高位到低位,每一位ans都加上所有符合条件的值,不重不漏 for(int j=0;j<digit[i];j++) if(j!=4&&!(digit[i+1]==6&&j==2)) ans+=dp[i][j]; if(digit[i]==4||(digit[i]==2&&digit[i+1]==6)) break;//继续循环不可能再有符合题意的值,故直接跳出 } return ans; } int main(){ int l,r; init(); while(scanf("%d%d",&l,&r),l){ printf("%d\n",solve(r+1)-solve(l));//区间相减,注意左闭右开 } return 0; }
时间: 2024-10-21 05:13:21