您的位置:首页 > 其它

HDU 5787 K-wolf Number

2016-08-03 21:41 211 查看
数位DP。dp[i][j][state] 表示最高位为i,数字为j,i位之后k-1个为state的方案数。例如1 2 3 4四个数字,state用1234表示。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-8;
void File()
{
freopen("D:\\in.txt","r",stdin);
freopen("D:\\out.txt","w",stdout);
}
inline int read()
{
char c = getchar();  while(!isdigit(c)) c = getchar();
int x = 0;
while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
return x;
}

LL L,R,dp[21][12][10010];
int k;
int f[21],q[10],sz;

bool check(int limit,int x)
{
int tmp=x,tmpsz=0;
if(tmp==0) tmpsz=1; while(tmp) tmpsz++, tmp=tmp/10;
if(tmpsz>limit) return 0;
if(tmpsz<limit-1) return 0;

sz=0;
if(x==0) f[sz++]=0;
while(x) f[sz++]=x%10, x=x/10;
if(tmpsz==limit-1) f[sz++]=0;
for(int i=0;i<sz;i++)
for(int j=i+1;j<=min(sz-1,i+k-1);j++)
if(f[i]==f[j]) return 0;
return 1;
}

bool Check(int x)
{
for(int i=0;i<sz;i++) if(x==f[i]) return 0;
return 1;
}

bool Ch(int x)
{
for(int i=0;i<sz-1;i++) if(x==f[i]) return 0;
return 1;
}

void init()
{
memset(dp,0,sizeof dp);
for(int i=0;i<=9;i++) dp[1][i][0]=1;
for(int i=2;i<=k;i++)
{
for(int j=0;j<=9;j++)
{
for(int s=0;s<=9999;s++)
{
if(!check(i-1,s)) continue;
if(!Check(j)) continue;
dp[i][j][s]=dp[i][j][s]+dp[i-1][f[sz-1]][s-f[sz-1]*q[sz-1]];
}
}
}

for(int i=k+1;i<=19;i++)
{
for(int j=0;j<=9;j++)
{
for(int s=0;s<=9999;s++)
{
if(!check(k-1,s)) continue;
if(!Check(j)) continue;
for(int u=0;u<=9;u++)
{
if(!Ch(u)) continue;
int p=s-f[sz-1]*q[sz-1];
dp[i][j][s]+=dp[i-1][f[sz-1]][p*10+u];
}
}
}
}
}

LL get(LL x)
{
LL res=0; int g[21];
int len=0; while(x) g[len++]=x%10,x=x/10;
for(int i=len;i>=1;i--) g[i]=g[i-1];

for(int i=1;i<=len-1;i++)
for(int j=1;j<=9;j++)
for(int s=0;s<=9999;s++)
res=res+dp[i][j][s];

for(int i=len;i>=1;i--)
{
int D; if(i==len) D=1; else D=0;
for(int j=D;j<g[i];j++)
{
bool ff=0;
for(int s=i+1;s<=min(len,i+k-1);s++) if(g[s]==j) ff=1;
if(ff) continue;
for(int s=0;s<=9999;s++)
{
if(dp[i][j][s]==0) continue;
bool fail=0; int m=i-1; m=min(k-1,m);
check(m,s);
for(int pos=sz-1;pos>=0;pos--)
for(int pre=i+1;pre<=min(len,i+pos-sz+k-1);pre++)
if(f[pos]==g[pre]) fail=1;
if(fail) continue;
res=res+dp[i][j][s];
}
}
for(int s=i+1;s<=min(len,i+k-1);s++) if(g[s]==g[i]) return res;
}
return res;
}

int main()
{
q[0]=1; for(int i=1;i<=5;i++) q[i]=10*q[i-1];
while(~scanf("%lld%lld%d",&L,&R,&k))
{
init();
printf("%lld\n",get(R+1)-get(L));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: