X - 1024 HDU - 5898 -数位DP

  • X - 1024

  •  HDU - 5898 
  • 题意:在给定区间内找到符合固定的数字的个数(一段连续的奇数个数为偶数, 一段连续的偶数个数为奇数)
  • 思路:数位dp[数位][到此前面连续的奇数个数][到此前面连续的偶数个数]

  • i为奇数时,1.新开始一段奇数那么前面的偶数个数得是奇数个,2或者延续前面的奇数那么f1不为0,3或者前导0情况
  • i为偶数数,1.新开始一段偶数那么前面的奇数个数得是偶数个,2或者延续前面的偶数那么f2不为0,3.或者前导0情况
  •  
  • #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define maxn 22
    int a[maxn],cas,t;
    ll st,ed,dp[maxn][maxn][maxn];
    ll dfs(int pos,int f1,int f2,bool limit)
    {
        if(pos==0)return (!f1||!(f1&1))&&(!(f2)||(f2&1));
        if(!limit&&dp[pos][f1][f2]!=-1)return dp[pos][f1][f2];
        int up=limit?a[pos]:9;
        ll res=0;
        for(int i=0; i<=up; i++)
        {
            if(!(f1||f2||i))res+=dfs(pos-1,0,0,limit&&i==up);//全部为0
            else if((i&1)&&((f1||f2&1)||(f1==0&&f2==0)))res+=dfs(pos-1,f1+1,0,limit&&i==up);
            //i为奇数时,可以是,1.新开始一段奇数那么前面的偶数个数得是奇数个,2或者延续前面的奇数那么f1不为0,3或者前导0情况
            else if(!(i&1)&&((f2||!(f1&1)||(f1==0&&f2==0))))res+=dfs(pos-1,0,f2+1,limit&&i==up);
            //i为偶数数时,可以是,1.新开始一段偶数那么前面的奇数数个数得是偶数个,2或者延续前面的偶数数那么f2不为0,3.或者前导0情况
        }
        if(!limit)dp[pos][f1][f2]=res;
        return res;
    }
    ll solve(ll x)
    {
        int pos=0;
        while(x)
        {
            a[++pos]=x%10;
            x/=10;
        }
        return dfs(pos,0,0,1);
    }
    int main()
    {
        scanf("%d",&t);
        memset(dp,-1,sizeof(dp));
        while(t--)
        {
            scanf("%lld%lld",&st,&ed);
            printf("Case #%d: %lld\n",++cas,solve(ed)-solve(st-1));
        }
        return 0;
    }
    
  •  

猜你喜欢

转载自blog.csdn.net/BePosit/article/details/84133446