#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int num[20];
ll dp[20][20][3];
//dp[i][k]
//i:数位
//k:3种状态,0-随便填,1-必须要选奇数,2-必须要选偶数
//pos为当前处理的数位(权重表示法,也就是剩下pos+1位待填数)
//have-状态;
//lim-后面的数是否可以任意填,1-不可以,0-可以
ll dfs(int x,int pos,ll cnt,int have,int lim)
{
int n,i;
ll ans=0;
if(pos<=0&&x==0) return 1;
if(pos<=0&&cnt==0) return 1;
if(pos<=0&&have==1&&cnt%2==0) return 1;
if(pos<=0&&have==2&&cnt%2==1) return 1;
if(pos==0) return 0;
//已经搜索过了
if(!lim&&dp[pos][cnt][have]!=-1)
return dp[pos][cnt][have];
//判断本位枚举的范围
n=lim?num[pos]:9;
for(i=0; i<=n; i++)
{
if(x==0&&i==0)
{
ans+=dfs(0,pos-1,0,0,0);
continue;
}
if(have==0)
{
if(i%2==1)
{
ans+=dfs(1,pos-1,cnt+1,1,lim&&i==n);
}
else
{
ans+=dfs(1,pos-1,cnt+1,2,lim&&i==n);
if(pos-1!=0) ans+=dfs(1,pos-1,0,1,lim&&i==n);
}
}
if(have==1&&i%2==1)
{
ans+=dfs(1,pos-1,cnt+1,1,lim&&i==n);
if((cnt+1)%2==0&&pos-1!=0)
ans+=dfs(1,pos-1,0,2,lim&&i==n);
}
if(have==2&&i%2==0)
{
ans+=dfs(1,pos-1,cnt+1,2,lim&&i==n);
if((cnt+1)%2==1&&pos-1!=0)
ans+=dfs(1,pos-1,0,1,lim&&i==n);
}
}
if(!lim)
dp[pos][cnt][have]=ans;
return ans;
}
int main()
{
int i,_,cas=0;
ll n,a1,a2,l,r;
memset(dp,0xff,sizeof(dp));
scanf("%d",&_);
while(_--)
{
scanf("%lld%lld",&l,&r);
if(l==1) a1=1;
else
{
n=l-1;
memset(num,0,sizeof(num));
i=0;
while(n)
{
num[++i]=n%10;
n/=10;
}
a1=dfs(0,i,0,0,1);
}
n=r;
memset(num,0,sizeof(num));
i=0;
while(n)
{
num[++i]=n%10;
n/=10;
}
a2=dfs(0,i,0,0,1);
//printf("%lld %lld\n",a1,a2);
printf("Case #%d: %lld\n",++cas,a2-a1);
}
return 0;
}
hdu5898 odd-even number 【数位DP】
最新推荐文章于 2019-08-26 15:23:00 发布