# 数位DP入坑

Hdu 2089 不要62

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long LL;

inline int read()
{
    char c=getchar();int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}

const int N=1e6+5;

int n,m;
int a[20],dgt;
int f[20][2;

int dfs(int dep,int pre,int sta,bool lim)
{
    if(!dep)
        return 1;
    if(!lim&&f[dep][sta!=-1)
        return f[dep][sta];
    int up=lim?a[dep]:9;
    int ans=0;
    for(int i=0;i<=up;++i)
    {
        if(i==4) continue;
        if(pre==6&&i==2) continue;
        ans+=dfs(dep-1,i,i==6,lim&&i==a[dep]);
    }
    if(!lim)
        f[dep][sta]=ans;
    return ans;
}

int solve(int x)
{
    for(dgt=0;x;a[++dgt]=x%10,x/=10);
    return dfs(dgt,0,0,1);
}

int main()
{
    while(1)
    {
        memset(f,-1,sizeof(f));
        n=read(),m=read();
        if(!n&&!m)
            break;
        cout<<solve(m)-solve(n-1)<<'
';
    }
    return 0;
}
View Code

Hdu 6148 Valley Numer

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long LL;

inline int read()
{
    char c=getchar();int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}

const int N=105;
const int mod=1e9+7;

int T,n;
char a[N];
int f[N][10][3];

int dfs(int dep,int pre,int turn,bool lim,bool invalid)
{
    if(dep==n+1)
        return invalid?0:1;
    if(!lim&&f[dep][pre][turn]!=-1)
        return f[dep][pre][turn];
    int up=lim?a[dep]-='0':9;
    int ans=0;
    for(int i=0;i<=up;++i)
    {
        if(turn==2&&i<pre)
            continue;
        int p=0;
        if(invalid) p=0;
        else if(i>pre) p=2;
        else if(i<pre) p=1;
        else p=turn;
        ans+=dfs(dep+1,i,p,lim&&i==a[dep],invalid&&i==0);
        ans%=mod;
    }
    if(!lim)
        f[dep][pre][turn]=ans;
    return ans;
}

int main()
{
    T=read();
    while(T--)
    {
        memset(f,-1,sizeof(f));
        scanf("%s",a+1);
        n=strlen(a+1);
        cout<<dfs(1,0,0,1,1)<<'
';
    }
    return 0;
}
View Code

Bzoj 1026: [SCOI2009]windy数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

typedef long long LL;

inline LL read()
{
    char c=getchar();LL num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}

LL A,B;
LL a[100],dgt;
LL f[100][10];

LL dfs(int dep,int pre,bool lim,bool invalid)
{
    if(!dep)
        return invalid?0:1;
    if(!lim&&!invalid&&f[dep][pre]!=-1)
        return f[dep][pre];
    int up=lim?a[dep]:9;
    LL ans=0;
    for(int i=0;i<=up;++i)
    {
        if(!invalid&&abs(i-pre)<2) continue;
        ans+=dfs(dep-1,i,lim&&i==a[dep],invalid&&i==0);
    }
    if(!lim&&!invalid)
        f[dep][pre]=ans;
    return ans;
}

LL solve(LL x)
{
    for(dgt=0;x;a[++dgt]=x%10,x/=10);
    return dfs(dgt,0,1,1);
}

int main()
{
    A=read(),B=read();
    memset(f,-1,sizeof(f));
    cout<<solve(B)-solve(A-1);
    return 0;
}
View Code

Poj 3252  Round Numbers

题意:问[l,r]中二进制位1比0少的数有多少个。

Sol: 记录当前层0,1个数。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

typedef long long LL;

inline int read()
{
    char c=getchar();int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}

int l,r;
int a[65],bit;
int f[65][65][65];

int dfs(int dep,int c0,int c1,bool lim,bool invalid)
{
    if(!dep)
        return (!invalid&&c0>=c1)?1:0;
    if(!lim&&f[dep][c0][c1]!=-1)
        return f[dep][c0][c1];
    int up=lim?a[dep]:1;
    int ans=0;
    for(int i=0;i<=up;++i)
        ans+=dfs(dep-1,c0+(i==0&&!invalid),c1+(i==1),lim&&i==up,invalid&&i==0);
    if(!lim)
        f[dep][c0][c1]=ans;
    return ans;
}

int solve(int x)
{
    for(bit=0;x;a[++bit]=x&1,x>>=1);
    return dfs(bit,0,0,1,1);
}

int main()
{
    memset(f,-1,sizeof(f));
    l=read(),r=read();
    cout<<solve(r)-solve(l-1);
    return 0;
}
View Code

P2518 [HAOI2010]计数

一个比较假的数位DP?但也是按照数位来做的。

Sol:无。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

typedef long long LL;

inline int read()
{
    char c=getchar();int num=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}

char num[61];
LL ans;int n,m;
int a[61],cnt[10];

LL c[60][60];
void init()
{
    c[0][0]=1;
    for(int i=1;i<=50;++i)
    {
        c[i][0]=1;
        for(int j=1;j<=i;++j)
            c[i][j]=c[i-1][j-1]+c[i-1][j];
    }
}

LL C(int n)
{
    LL res=1;
    for(int i=0;i<10;++i)
        if(cnt[i])
            res*=c[n][cnt[i]],n-=cnt[i];
    return res;
}

int main()
{
    init();
    scanf("%s",num+1);
    for(n=1;num[n];++n)
        a[n]=num[n]-'0',++cnt[num[n]-'0'];
    m=--n;
    for(int i=1;i<=n;++i)
    {
        --m;
        for(int j=0;j<a[i];++j)
            if(cnt[j])
                --cnt[j],ans+=C(m),++cnt[j];
        --cnt[a[i]];
    }
    cout<<ans;
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/lovewhy/p/9880069.html