odd-even number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 648 Accepted Submission(s): 357
Total Submission(s): 648 Accepted Submission(s): 357
Problem Description
For a number,if the length of continuous odd digits is even and the length of continuous even digits is odd,we call it odd-even number.Now we want to know the amount of odd-even number between L,R(1<=L<=R<= 9*10^18).
Input
First line a t,then t cases.every line contains two integers L and R.
Output
Print the output for each case on one line in the format as shown below.
Sample Input
2 1 100 110 220
Sample Output
Case #1: 29 Case #2: 36
Source
题意:求[L,R内“奇偶数”的个数,奇偶数定义:如果一个数中连续的奇数有偶数个,连续的偶数有奇数个,那么这个数就是“奇偶数”
分析:简单数位dp,我们用dp[i][num][cnt],表示第i位为num,如果num为奇数,那么cnt表示和num连续的奇数有cnt个,num为偶数就表示和num连续的偶数有cnt个,显然0<=num<=9,cnt<19;对于i不是最后一位的情况,要考虑中间的cnt满足条件才能向后转移,用记忆化dfs写方便些。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
int digit[21];
LL dp[21][11][21];
LL dfs(int l,int num,int cnt,bool zero,bool jude)
{
if(l==0)
{
if(num==10) return 0;
if((num&1)&&!(cnt&1)) return 1;
if(!(num&1)&&(cnt&1)) return 1;
return 0;
}
if(!jude&&dp[l][num][cnt]!=-1) return dp[l][num][cnt];
int x=jude?digit[l]:9;
LL ans=0;
for(int i=0;i<=x;i++)
{
if(zero&&i==0) ans+=dfs(l-1,num,cnt,zero&&i==0,jude&&i==x);//一直是前导零,那么一直填10,不管他
else
{
int a,b;
if(num==10) a=i,b=1;//表明之前一直是前导零,从这位开始填非零数字
else
{
if(i&1)
{
if(num&1) a=i,b=cnt+1;
else
{
if(!(cnt&1)) continue;
a=i;
b=1;
}
}
else
{
if(!(num&1)) a=i,b=cnt+1;
else
{
if(cnt&1) continue;
a=i;
b=1;
}
}
}
ans+=dfs(l-1,a,b,zero&&i==0,jude&&i==x);
}
}
if(!jude) dp[l][num][cnt]=ans;
return ans;
}
LL get(LL x)
{
int l=0;
while(x)
{
digit[++l]=x%10;
x/=10;
}
return dfs(l,10,1,true,true);///考虑前导零,如果一直都是前导零,那么我就一直用10填充,到最后跑断一下,10为特殊值
}
int main()
{
memset(dp,-1,sizeof(dp));
int T;
scanf("%d",&T);
for(int ca=1;ca<=T;ca++)
{
LL L,R;
scanf("%lld%lld",&L,&R);
printf("Case #%d: %lld\n",ca,get(R)-get(L-1));
}
return 0;
}