杭州人称那些傻乎乎粘嗒嗒的人为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
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
int dp[21][2];//dp[i][j]表示第i位数字是否为6的符合条件的数目
int p[20];//用来存放各位数
typedef long long ll;
int dfs(int pos,int pre,int sta,bool limit)//pos表示当前位数,pre表前一位是多少,sta表是否
{//前一位是6,limit表是否达到上限,也就是当前位数所能达到的最大值
if(pos==-1)
return 1;
if(!limit&&dp[pos][sta]!=-1)//减小复杂度,不用重复计算
return dp[pos][sta];
int up=limit?p[pos]:9;
int ans=0;
rep(i,0,up)
{
if(i==4||(i==2&&pre==6))continue;
ans+=dfs(pos-1,i,i==6,limit && i==p[pos]);
}
if(!limit)
dp[pos][sta]=ans;
return ans;
}
ll solve(int a)
{
int tot=0;
while(a)
{
p[tot++]=a%10;
a/=10;
}
return dfs(tot-1,-1,0,true);
}
int main()
{
ll n_,m_;
while(cin>>n_>>m_&&(n_||m_)){
memset(dp,-1,sizeof(dp));
ll ans1=solve(n_-1);//这里注意是n_-1,如果是直接相减就会多减去,使区间变小,可以举[1,10]
ll ans2=solve(m_);
cout<<ans2-ans1<<endl;
}
return 0;
}
下面是WA的代码有没有知道为啥,大牛们帮忙look一下,谢谢
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=1000000;
int dp[11][11];
#define rep(i,a,b) for(int i=a;i<=b;i++)
void getdp()
{
dp[0][0]=1;
rep(i,1,9)
{
rep(j,0,9)
{
if(j==4)
dp[i][j]=0;
else if(j==6)
{
rep(k,0,9)
dp[i][j]+=dp[i-1][k];
dp[i][j]-=dp[i-1][2];
}
else
rep(k,0,9)
dp[i][j]+=dp[i-1][k];
}
}
}
ll solve(int a)
{
int f[10]={0};
int tot=0;
while(a)
{
f[++tot]=a%10;
a/=10;
}
ll ans=0;
for(int i=tot;i>=1;i--)
{
rep(j,0,f[i]-1)
if((f[i+1]!=6&&j!=2)||j!=4)
ans+=dp[i][j];
if((f[i+1]==6&&f[i]==2)||f[i]==4)
break;
}
return ans;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
getdp();
rep(i,1,9)
{
rep(j,0,9)
cout<<dp[i][j]<<" ";
cout<<endl;
}
int n;
int m;
while(cin>>n>>m&&(n||m))
{
//cout<<solve(m+1);
cout<<solve(m+1)-solve(n)<<endl;
}
return 0;
}