poj2282(数位dp)
时间:2014-05-12 23:51:12
收藏:0
阅读:470
题意:计算a-b中各个数字出现的个数;
解法:数位dp(思想都是先算1-b的个数,然后减掉1-a中的个数),1-9数字的计算和前边计算1的那一篇数位dp差不多,计算0时候要加一维表示前缀是否全是0;
代码:
/******************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;
#define eps 1e-8
const double pi=acos(-1.0);
typedef long long LL;
const int Max=10100;
const int INF=1000000007;
int dp[20][20][2];
int dp0[20][20][2][2];
int tool[20];
LL fac[20];
int com=0;
int st,en;
void init()
{
fac[0]=1;fac[1]=10;
for(int i=2;i<10;i++)
fac[i]=fac[i-1]*10;
}
int dfs0(int pre,int now,bool iflow,bool ifall0)
{
if(pre==0)
return now==0;
if(dp0[pre][now][iflow][ifall0]!=-1)
return dp0[pre][now][iflow][ifall0];
int en=iflow? 9: tool[pre-1];
int ans=0;
if(now==0&&!ifall0&&!iflow)
ans+=com%fac[pre]+1;
if(now==0&&!ifall0&&iflow)
ans+=fac[pre];
for(int i=0;i<=en;i++)
ans+=dfs0(pre-1,i,iflow||i!=en,ifall0&&i==0);
return dp0[pre][now][iflow][ifall0]=ans;
}
int dfs(int pre,int now,bool iflow,int who)
{
if(pre==0)
return now==who;
if(dp[pre][now][iflow]!=-1)
return dp[pre][now][iflow];
int en=iflow? 9 : tool[pre-1];
int ans=0;
if(now==who&&iflow)
ans+=fac[pre];
if(now==who&&(!iflow))
ans+=com%fac[pre]+1;
for(int i=0;i<=en;i++)
ans+=dfs(pre-1,i,iflow||(i!=en),who);
return dp[pre][now][iflow]=ans;
}
int solve(int k,int t)
{
com=k;
int p=0;
if(k==0&&t==0)
return 1;
while(k)
{
tool[p++]=k%10;
k/=10;
}
int ans=0;
if(t==0)
{
memset(dp0,-1,sizeof dp0);
ans+=dfs0(p-1,0,1,1);
for(int i=1;i<=tool[p-1];i++)
ans+=dfs0(p-1,i,i!=tool[p-1],0);
return ans;
}
else
{
memset(dp,-1,sizeof dp);
for(int i=0;i<=tool[p-1];i++)
ans+=dfs(p-1,i,i!=tool[p-1],t);
return ans;
}
}
int main()
{
init();
while(scanf("%d%d",&en,&st)==2)
{
if(st<en)
swap(st,en);
if(st==0&&en==0)
break;
cout<<solve(st,0)-solve(en-1,0);
for(int i=1; i<10; i++)
{
cout<<" "<<solve(st,i)-solve(en-1,i);
}
cout<<‘\n‘;
}
return 0;
}
评论(0)