http://acm.hdu.edu.cn/showproblem.php?pid=5898
题意:统计 连续的奇数必须是偶数个,连续的偶数必须是奇数个。。的个数
思路:dp[ i ] [ j ] [ k ] 前i位 上一位是j 连续的奇数或者偶数有k。。
blog里面数位dp比较少,贴一个上来。。。
代码:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
int a[20];
ll dp[20][11][20];//不同题目状态不同
ll dfs(int pos,int state,int ok,bool lead/*前导零*/,bool limit/*数位上界变量*/)
{
if(pos==-1&&(state+ok)%2==1) return 1;
if(pos==-1&&(state+ok)%2==0) return 0;
if(!limit && !lead && dp[pos][state][ok]!=-1) return dp[pos][state][ok];
int up=limit?a[pos]:9;
ll ans=0;
if(lead){
for(int i=0;i<=up;i++){
ans+=dfs(pos-1,i,1,lead && i==0,limit && i==a[pos]);
}
}
else if((state+ok)%2==1){
for(int i=0;i<=up;i++){
if((i+state)%2==0)
ans+=dfs(pos-1,i,ok+1,lead && i==0,limit && i==a[pos]);
else
ans+=dfs(pos-1,i,1,lead && i==0,limit && i==a[pos]);
}
}
else{
for(int i=0;i<=up;i++){
if((i+state)%2==0)
ans+=dfs(pos-1,i,ok+1,lead && i==0,limit && i==a[pos]);
}
}
if(!limit && !lead) dp[pos][state][ok]=ans;
return ans;
}
ll solve(ll x)
{
int pos=0;
a[0]=0;
while(x)
{
a[pos++]=x%10;//编号为[0,pos),
x/=10;
}
return dfs(pos-1/*从最高位开始枚举*/,10,1,true,true);
}
int main()
{
ll le,ri;
int cas=1;
int t;
scanf("%d",&t);
memset(dp,-1,sizeof(dp));
while(t--){
scanf("%lld%lld",&le,&ri);
printf("Case #%d: %lld
",cas++,solve(ri)-solve(le-1));
}
}