Y - odd-even number

题目链接:https://cn.vjudge.net/contest/194559#problem/Y

大意:连续奇数的个数是偶数;连续偶数的个数是奇数的这种数的个数

分析:刚开始想着pre_ou,pre_ji这两种状态,很麻烦。后来旁敲侧击的知道了用一个judge(yes)标志一下是否满足就可以了。中间有的小地方需要注意

  这道题需要学习的地方就是状态,然后dfs的时候细心

代码如下:


#include<iostream>
#include<string.h>
using namespace std;
typedef long long ll;
int dig[20];
ll dp[20][3][3];
ll dfs(int pos,int pre,int lead,int yes,int limit)
{
    if(pos==0)
        return yes==1?1:0;
    if(lead==1&&dp[pos][pre][yes]!=-1&&!limit)
        return dp[pos][pre][yes];
    ll ans=0;
    int up=limit?dig[pos]:9;
    for(int i=0;i<=up;i++)
    {
        if(lead==0)
        {
            if(i==0)
                ans+=dfs(pos-1,0,0,1,limit&&i==up);
            else
                ans+=dfs(pos-1,i%2,1,i%2==1?0:1,limit&&i==up);//这地方一开始写错了
        }
        else//无前导0
        {
            if(i%2==1)
            {
                if(pre%2==1)
                    ans+=dfs(pos-1,1,1,yes==1?0:1,limit&&i==up);
                else//转折点,过去全是偶数,如今转折成了奇数
                {
                    if(yes==1)//前边满足条件,此前这位是奇数,个数是1个,故搜索时yes==0
                        ans+=dfs(pos-1,1,1,0,limit&&i==up);
                }
             }
            else//当前位是偶数
            {
                if(pre%2==0)
                    ans+=dfs(pos-1,0,1,yes==1?0:1,limit&&i==up);
                else//转折点
                {
                    if(yes==1)
                        ans+=dfs(pos-1,0,1,1,limit&&i==up);
                }
             }
          }
    }
    if(!limit&&lead)
        dp[pos][pre][yes]=ans;
    return ans;
}
    ll solve(ll x)
    {
        memset(dig,0,sizeof(dig));
        int id=0;
        while(x)
        {
            dig[++id]=x%10;
            x/=10;
        }
        return dfs(id,0,0,1,1);
    }






int main()
{
    memset(dp,-1,sizeof(dp));
    int T;
    ll a,b;
    int lala=1;
    cin>>T;
    while(T--)
    {
        cin>>a>>b;
        cout<<"Case "<<"#"<<lala<<":"<<" "<<solve(b)-solve(a-1)<<endl;
        lala++;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值