www.cnblogs.com/shaokele/
橘猫##
Time Limit: 1 Sec
Memory Limit: 512 MBDescription###
NiroBC 有了一间小屋,真是太好了,终于可以养猫了。
NiroBC 想养N 只猫,编号为1……N。
NiroBC 希望,第i 只猫为橘猫,当且仅当在i 的十进制表示下(不含前导零),每个阿拉伯数字出现的次数都是偶数。
NiroBC 想知道她会养多少只橘猫。
Input###
一行一个正整数N,表示猫的数量。
Output###
一行一个整数,表示橘猫的数量。
Sample Input###
65
2360596325
Sample Output###
5
7080461
题目地址:yyhs校内题库
题目大意: 题目已经很简洁了>_<
题解:
数位dp裸题
AC代码
#include <cstdio>
#include <algorithm>
#define ll long long
using namespace std;
int len;
int a[20];
ll n;
ll dp[20][10][1024][2][2];
int main(){
scanf("%lld",&n);
while(n){
a[++len]=n%10;
n/=10;
}
for(int i=1;i<=len/2;i++)
swap(a[i],a[len-i+1]);
//dp[i][j][k][p][q]
//第i位,取j,状态为k,是否贴上界,是否有前导0
dp[1][0][0][0][1]=1;
for(int i=1;i<a[1];i++)
dp[1][i][1<<i][0][0]=1;
dp[1][a[1]][1<<a[1]][1][0]=1;
for(int i=1;i<len;i++){
//有前导0
dp[i+1][0][0][0][1]+=dp[i][0][0][0][1];
for(int p=1;p<=9;p++)
dp[i+1][p][1<<p][0][0]+=dp[i][0][0][0][1];
//没前导0
for(int j=0;j<=9;j++)
for(int k=0;k<(1<<10);k++){
for(int p=0;p<=9;p++)
dp[i+1][p][k^(1<<p)][0][0]+=dp[i][j][k][0][0];
for(int p=0;p<a[i+1];p++)
dp[i+1][p][k^(1<<p)][0][0]+=dp[i][j][k][1][0];
}
//贴上界
for(int k=0;k<(1<<10);k++)
dp[i+1][a[i+1]][k^(1<<a[i+1])][1][0]+=dp[i][a[i]][k][1][0];
}
ll ans=0;
for(int i=0;i<=9;i++)
for(int j=0;j<=1;j++)
for(int k=0;k<=1;k++)
ans+=dp[len][i][0][j][k];
printf("%lld
",ans-dp[len][0][0][0][1]);
return 0;
}