题目链接:https://cn.vjudge.net/contest/194559#problem/Y
大意:连续奇数的个数是偶数;连续偶数的个数是奇数的这种数的个数
分析:刚开始想着pre_ou,pre_ji这两种状态,很麻烦。后来旁敲侧击的知道了用一个judge(yes)标志一下是否满足就可以了。中间有的小地方需要注意
这道题需要学习的地方就是状态,然后dfs的时候细心
代码如下:
#include<iostream>
#include<string.h>
using namespace std;
typedef long long ll;
int dig[20];
ll dp[20][3][3];
ll dfs(int pos,int pre,int lead,int yes,int limit)
{
if(pos==0)
return yes==1?1:0;
if(lead==1&&dp[pos][pre][yes]!=-1&&!limit)
return dp[pos][pre][yes];
ll ans=0;
int up=limit?dig[pos]:9;
for(int i=0;i<=up;i++)
{
if(lead==0)
{
if(i==0)
ans+=dfs(pos-1,0,0,1,limit&&i==up);
else
ans+=dfs(pos-1,i%2,1,i%2==1?0:1,limit&&i==up);//这地方一开始写错了
}
else//无前导0
{
if(i%2==1)
{
if(pre%2==1)
ans+=dfs(pos-1,1,1,yes==1?0:1,limit&&i==up);
else//转折点,过去全是偶数,如今转折成了奇数
{
if(yes==1)//前边满足条件,此前这位是奇数,个数是1个,故搜索时yes==0
ans+=dfs(pos-1,1,1,0,limit&&i==up);
}
}
else//当前位是偶数
{
if(pre%2==0)
ans+=dfs(pos-1,0,1,yes==1?0:1,limit&&i==up);
else//转折点
{
if(yes==1)
ans+=dfs(pos-1,0,1,1,limit&&i==up);
}
}
}
}
if(!limit&&lead)
dp[pos][pre][yes]=ans;
return ans;
}
ll solve(ll x)
{
memset(dig,0,sizeof(dig));
int id=0;
while(x)
{
dig[++id]=x%10;
x/=10;
}
return dfs(id,0,0,1,1);
}
int main()
{
memset(dp,-1,sizeof(dp));
int T;
ll a,b;
int lala=1;
cin>>T;
while(T--)
{
cin>>a>>b;
cout<<"Case "<<"#"<<lala<<":"<<" "<<solve(b)-solve(a-1)<<endl;
lala++;
}
return 0;
}