数位DP

匿名 (未验证) 提交于 2019-12-02 23:56:01

1  int pos=0; 2     while(k) 3     { 4         num[++pos]=k%10; 5         k/=10; 6     }

 1 inline int dfs(int pos,int pre,int sta,bool limit)//pos:位数,pre:前驱,sta前一位是否是6,若不是则可以记忆化,否则因  2                                                   //这一位2不能取而不能记忆化 limit:判断当前位的枚举上限   3 {  4     if(pos==0) return 1;//表示找到了最低位仍合法证明找到了一个数   5     if(!limit&&dp[pos][sta]!=-1) return dp[pos][sta];//记忆化不是上限的0-9过程   6     int up,sum=0;  7     if(!limit) up=9; else up=num[pos];//判断这位的枚举上限   8     for(int i=0;i<=up;i++)//枚举这一位的所有可能   9     { 10         if(i==4) continue;//去掉4的情况  11         if(pre==6&&i==2) continue;//去掉前驱是6,这位是2的情况  12         sum+=dfs(pos-1,i,i==6,limit&&(i==num[pos]));//搜  13     } 14     if(!limit) dp[pos][sta]=sum; 15     return sum; 16 }

#include<cstdio> #include<iostream> #include<cstring> #include<algorithm>  using namespace std;  int dp[20][2],num[20];  inline int dfs(int pos,int pre,int sta,bool limit) {     if(pos==0) return 1;     if(!limit&&dp[pos][sta]!=-1) return dp[pos][sta];     int up,sum=0;     if(!limit) up=9; else up=num[pos];     for(int i=0;i<=up;i++)     {         if(i==4) continue;         if(pre==6&&i==2) continue;         sum+=dfs(pos-1,i,i==6,limit&&(i==num[pos]));     }     if(!limit) dp[pos][sta]=sum;     return sum; }  inline int solve(int k) {     int pos=0;     while(k)     {         num[++pos]=k%10;         k/=10;     }     return dfs(pos,0,0,true); }  int main() {     int m,n;     memset(dp,-1,sizeof(dp));     while(1)     {         scanf("%d%d",&m,&n);         if(m==0&&n==0) return 0;         printf("%d\n",solve(n)-solve(m-1));     }     return 0; }

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!