橘猫

**问题 B: 橘猫** **时间限制: 1 Sec 内存限制: 512 MB**
**题目描述** NiroBC 有了一间小屋,真是太好了,终于可以养猫了。 NiroBC 想养N 只猫,编号为1……N。 NiroBC 希望,第i 只猫为橘猫,当且仅当在i 的十进制表示下(不含前导零),每个阿拉伯数字出现的次数都是偶数。 NiroBC 想知道她会养多少只橘猫。 **输入** 一行一个正整数N,表示猫的数量。 **输出** 一行一个整数,表示橘猫的数量。 **样例输入** 65

2360596325
样例输出
5

7080461
提示
样例解释1
总共有5 只橘猫,编号分别为11; 22; 33; 44; 55。
样例解释2
解释略,另外,这个输入的值是出题人的QQ 号。
数据范围
对于30% 的数据,1<= N <= 10^6。
对于另外20% 的数据,N 是10 的整次幂。
对于所有数据,1 <= N <= 10^18。
题解:
这是一道数位dp裸题,具体在代码中讲解。
C o d e : Code: Code

#include<iostream> 
#include<cmath> 
#include<cstring> 
#include<cstdio> 
#include<algorithm> 
#include<cstdlib> 
#define ll long long 
using namespace std; 
ll dp[20][60000],bit[20]; 
bool check(int s)//求出答案
{ 
    int num[10]; 
    for(int i=0;i<10;i++) 
    { 
        num[i]=s%3; 
        s/=3; 
    } 
    for(int i=0;i<10;i++) 
        if(num[i]!=0) 
            if(num[i]==1)return false; 
    return true; 
} 
int work(int x,int s)//加入x,更新状态
{ 
    int num[10]; 
    for(int i=0;i<10;i++) 
    { 
        num[i]=s%3; 
        s/=3; 
    } 
    if(num[x]==0)num[x]=1;else
    num[x]=3-num[x]; 
    int sum=0; 
    for(int i=9;i>=0;i--) 
    { 
        sum*=3; 
        sum+=num[i]; 
    } 
    return sum; 
} 
ll dfs(int pos,int s,int flag,int zero)//pos表示第几位,s表示状态,flag表示是否贴上界,zero表示前导零
{ 
    if(pos==-1)return check(s); 
    if(!flag&&dp[pos][s]!=-1) 
        return dp[pos][s]; 
    ll ans=0;int t; 
    if(flag)t=bit[pos];else t=9; 
    for(int i=0;i<=t;i++) 
        ans+=dfs(pos-1,(zero&&i==0)?0:work(i,s),flag&&i==t,zero&&i==0); 
    if(!flag)dp[pos][s]=ans; 
    return ans; 
} 
int main() 
{ 
    ll n; 
    memset(dp,-1,sizeof(dp)); 
    scanf("%lld",&n); 
    int len=0; 
    while(n) 
    { 
        bit[len++]=n%10; 
        n/=10; 
    } 
    printf("%lld\n",dfs(len-1,0,1,1)-1); //减掉等于0的情况
    return 0; 
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JackflyDC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值