Problem Description
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
Input
输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。
Output
对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。
Sample Input
1 100
0 0
Sample Output
80
思路:似乎可以暴力?稍微修改一下,假定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; }
原文地址:https://www.cnblogs.com/lllxq/p/9426701.html
时间: 2024-11-09 05:30:34