数位dp

来源:互联网 发布:网络常见的拓扑形式有 编辑:程序博客网 时间:2024/06/16 04:35
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int maxn=1e6;int dp[10][12];//dp[i][j]代表第i位放数值j后面位数任意放值(0-9)有多少合法放法void init(){     for(int i=1;i<=7;i++)       for(int j=0;j<=9;j++)       {           if(i==1)         //dp[i][j],i==1时的初始化           {               dp[i][j]=(j==4?0:1);               continue;           }           int s=0;           for(int k=0;k<=9;k++)//dp[i][j]的值只与下一位有关,           {                    //当前位值j,下一位k, dp[i][j]=合法sum(j,dp[i-1][k])                if(j==6&&k==2||j==4||k==4) continue;               s=s+dp[i-1][k];           }           dp[i][j]=s;       }}int cal(int x) //计算0-x的合法值,从x的高位到低位依次算.{    if(x==0) return 1;    int num=1,a[12];    while(x)    {        a[num++]=x%10;        x=x/10;    }    int ans=0;    for(int i=0;i<a[num-1]+(num==2?1:0);i++) ans=ans+dp[num-1][i]; //最高位确定,,    for(int i=num-1;i>=2;i--)   //逐步确定高位值,即不再变化.    {        if(a[i]==4) break;//bug 确定的4后面的放法全作废        for(int j=0;j<a[i-1]+(i==2?1:0);j++)         {            if(j==4||a[i]==6&&j==2) continue;            ans=ans+dp[i-1][j];        }        if(a[i]==6&&a[i-1]==2) break;//bug 同理确定的62后面的放法也全作废    }    return ans;}int main(){    //freopen("C:/Users/hzy/Desktop/11.txt","r",stdin);    init();    int n,m;    while(scanf("%d%d",&n,&m)!=EOF)    {        if(n==0&&m==0) break;        if(n>m) swap(n,m);        cout<<cal(m)-cal(n-1)<<endl;    }    return 0;}/*4279 482513228 262412705 2626224303 26460*/

原创粉丝点击