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;
}