odd-even number (数位dp)

来源:互联网 发布:linux 建立多级目录 编辑:程序博客网 时间:2024/04/28 12:21

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: 29Case #2: 36


题目大概:

在n和m之间存在多少个数,各位数之间有着连续奇数个偶数,偶数个奇数。

思路:

数位dp。

在递归里加几个条件,进行判断。

是否有前导零,是否有零。

前一个数是奇数,后一个是否是奇数,

前一个数是偶数,后一个是否是偶数,

最后判断一下,。

代码:


#include <iostream>#include <cstring>#include <cstdio>using namespace std;typedef long long LL;int a[20];LL dp[20][30][30];LL sove(int pos,int qian,int sum,int b,int limit){    if(pos==-1)return (qian&1)!=(sum&1);    if(!limit&&dp[pos][qian][sum]!=-1)return dp[pos][qian][sum];    LL ans=0;    int end=limit?a[pos]:9;    for(int i=0;i<=end;i++)    {        if(b)        {            if(i==0)ans+=sove(pos-1,0,0,1,limit&&i==end);            else ans+=sove(pos-1,i&1,1,0,limit&&i==end);        }        else        {            if(i&1){                if(qian&1)ans+=sove(pos-1,i&1,sum+1,0,limit&&i==end);            else            {                if(sum&1)ans+=sove(pos-1,i&1,1,0,limit&&i==end);            }            }            else            {                if(qian&1)                {                    if(!(sum&1))ans+=sove(pos-1,i&1,1,0,limit&&i==end);                }                else ans+=sove(pos-1,i&1,sum+1,0,limit&&i==end);            }        }    }    if(!limit)dp[pos][qian][sum]=ans;    return ans;}LL go(LL x){    LL pos=0;    while(x)    {        a[pos++]=x%10;        x/=10;    }    return sove(pos-1,0,0,1,1);}int main(){    int t;    LL n,m;    scanf("%I64d",&t);    for(int i=1;i<=t;i++)    {   memset(dp,-1,sizeof(dp));        scanf("%I64d%I64d",&n,&m);        printf("Case #%d: %I64d\n",i,go(m)-go(n-1));    }    return 0;}

原创粉丝点击