hdu5787 K-wolf Number【数位dp】

来源:互联网 发布:最好的解剖软件 编辑:程序博客网 时间:2024/06/01 09:28
#include<bits/stdc++.h>using namespace std;typedef long long ll;int num[20],k;ll dp[20][2048];//dp[i][k]//i:数位,k:前面数字的状态//pos为当前处理的数位(权重表示法,也就是剩下pos+1位待填数)//have-状态;//lim-后面的数是否可以任意填,1-不可以,0-可以ll dfs(int pre,int pos,int a0,int a1,int a2,int a3,int a4,int have,int lim){    //printf("%d %d %d %d %d %d\n",pos,a0,a1,a2,a3,a4);    int n,i,a[10];    a[0]=a0;    a[1]=a1;    a[2]=a2;    a[3]=a3;    a[4]=a4;    ll ans=0;    if(pos==0) return 1;    //已经搜索过了    if(!lim&&dp[pos][have]!=-1)        return dp[pos][have];    for(int i=0; i+1<k; i++)    {        a[i]=a[i+1];    }    //判断本位枚举的范围    n=lim?num[pos]:9;    for(i=0; i<=n; i++)    {        if(pre==0&&i==0)        {            ans+=dfs(0,pos-1,-1,-1,-1,-1,-1,0,lim&&i==n);            continue;        }        int f=0;        for(int j=0; j<k; j++)            if(a[j]==i)            {                f=1;                break;            }        if(f) continue;        a[k-1]=i;        int now=0;        for(int j=0; j<5; j++)        {            if(a[j]==-1) continue;            now+=1<<a[j];        }        ans+=dfs(1,pos-1,a[0],a[1],a[2],a[3],a[4],now,lim&&i==n);    }    if(!lim)        dp[pos][have]=ans;    return ans;}ll get(ll x){    memset(dp,0xff,sizeof(dp));    if(x==0) return 1;    else    {        x;        memset(num,0,sizeof(num));        int i=0;        while(x)        {            num[++i]=x%10;            x/=10;        }        return dfs(0,i,-1,-1,-1,-1,-1,0,1);    }}int main(){    int i,_,cas=0;    ll n,a1,a2,l,r;    while(scanf("%lld%lld%d",&l,&r,&k)!=EOF)    {        a1=get(l-1);        a2=get(r);        //printf("%lld %lld\n",a1,a2);        printf("%lld\n",a2-a1);    }    return 0;}
0 0
原创粉丝点击