Description
连续的偶数位数量为奇数,连续的奇数为数量为偶数的数字被称为奇偶数,问介于区间 [L,R] [ L , R ] 之间的奇偶数个数
Input
第一行一整数 T T 表示用例组数,每组用例输入两个整数
Output
输出区间 [L,R] [ L , R ] 中奇偶数个数
Sample Input
2
1 100
110 220
Sample Output
Case #1: 29
Case #2: 36
Solution
数位 DP D P ,问题转化为求 [1,N] [ 1 , N ] 中奇偶数个数,以 dp[pos][pre][num] d p [ p o s ] [ p r e ] [ n u m ] 表示已经确定高位的前 pos p o s 位,上一位是 pre p r e ,且连续的奇偶性相同的位有 num n u m 位的方案数,如果 pre p r e 和 num n u m 奇偶性相同,则下一位必然还需和 pre p r e 的奇偶性相同,否则下一位任意取即可
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll l,r,dp[22][11][22];
int T,n,a[22];
ll dfs(int pos,int pre,int num,int lead,int fp)
{
if(pos==-1)return (pre+num)%2;
if(!lead&&!fp&&dp[pos][pre][num]!=-1)return dp[pos][pre][num];
ll ans=0;
int fpmax=fp?a[pos]:9;
if(lead)
{
for(int i=0;i<=fpmax;i++)
ans+=dfs(pos-1,i,1,lead&&i==0,fp&&i==fpmax);
}
else if((pre+num)%2)
{
for(int i=0;i<=fpmax;i++)
if((i+pre)%2)ans+=dfs(pos-1,i,1,lead&&i==0,fp&&i==fpmax);
else ans+=dfs(pos-1,i,num+1,lead&&i==0,fp&&i==fpmax);
}
else
{
for(int i=0;i<=fpmax;i++)
if((i+pre)%2==0)ans+=dfs(pos-1,i,num+1,lead&&i==0,fp&&i==fpmax);
}
if(!lead&&!fp)dp[pos][pre][num]=ans;
return ans;
}
ll Solve(ll x)
{
n=0;
while(x)
a[n++]=x%10,x/=10;
return dfs(n-1,10,1,1,1);
}
int main()
{
int res=1;
scanf("%d",&T);
memset(dp,-1,sizeof(dp));
while(T--)
{
scanf("%I64d%I64d",&l,&r);
printf("Case #%d: %I64d\n",res++,Solve(r)-Solve(l-1));
}
return 0;
}