标签:input 个数 状态转移方程 int mes code can nbsp bre
Problem Description
思路:似乎可以暴力?稍微修改一下,假定n,m<1e12把;进行数位dp,设状态f[i][j]表示位数为i,最高位为j的所有数中满足题意的数有多少,则状态转移方程为:
if(j==4) f[i][j]=0
else if(j!=6) f[i][j]=sum{f[i-1][k]}(k=0,1,2,3,4,5,...,9)
else f[i][j]=sum{f[i-1][k] }(k=0,1,3,4,5,...,9)
那区间[0,n)中满足题意的数就为sum{f[i][k]}(k=0~a[i]-1)(a[i]表示n的第i位数字),再减去其中包含的一些不吉利数的个数;
AC代码:
#include <iostream> #include<cstdio> typedef long long ll; using namespace std; ll n,m; ll dp[15][15]; void get_dp(){ dp[0][0]=1; for(ll i=1;i<=12;i++){ for(ll j=0;j<=9;j++){ dp[i][j]=0; if(j==4) continue; else{ for(ll k=0;k<=9;k++) dp[i][j]+=dp[i-1][k]; if(j==6) dp[i][j]-=dp[i-1][2]; } } } } ll len=0,a[15]; void depart(ll x){ len=0; while(x){ a[++len]=x%10; x/=10; } } ll cal(ll x){ depart(x);//将x的各个位拆开 ll ret=0; for(ll i=len;i>=1;i--){ if(i<len&&a[i+1]==4) break; if(i<len-1&&a[i+1]==2&&a[i+2]==6) break; for(ll j=a[i]-1;j>=0;j--){ if(i==len) ret+=dp[i][j]; else{ if(!(a[i+1]==6&&j==2)) ret+=dp[i][j]; } } } return ret; } int main() { while(scanf("%lld%lld",&n,&m)!=EOF&&(n||m)){ get_dp(); printf("%lld\n",cal(m+1)-cal(n)); } return 0; }
标签:input 个数 状态转移方程 int mes code can nbsp bre
原文地址:https://www.cnblogs.com/lllxq/p/9426701.html