bzoj1026 [SCOI2009]windy数 数位DP

先用fi,j表示在长度为i时尾数为j,然后我们dfs位数容斥统计也可以,直接分类统计也可以

复杂度……额,casenumber*200?反正小到发指不用理他23333333

/**************************************************************
    Problem: 1026
    User: BPM136
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1272 kb
****************************************************************/
 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define down(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
#define N 12
#define M 10
int f[N][M];
int n,m;
 
void DP()
{
    memset(f,0,sizeof(f));
    fo(i,0,9)f[1][i]=1;
    fo(i,2,10)
    {
        fo(j,0,9)
        {
            fo(k,0,9)
            if(abs(j-k)>1)
            f[i][j]+=f[i-1][k];
        }
    }
}
 
int get(int x)
{
    int A[N];memset(A,0,sizeof(A));
    int cnt=0,tot=x;
    while(tot)
    {
        A[cnt++]=tot%10;
        tot/=10;
    }
    int ans=0;
    fo(i,1,cnt-1)
    {
        fo(j,1,9)
        {
            ans+=f[i][j];
        }
    }
    fo(i,1,A[cnt-1]-1)ans+=f[cnt][i];
    down(i,cnt-1,1)
    {
        fo(j,0,A[i-1]-1)
        if(abs(j-A[i])>1)
        {
            ans+=f[i][j];
        }
        if(abs(A[i]-A[i-1])<=1)break;
    }
    return ans;
}
 
int main()
{
    scanf("%d%d",&n,&m);
    DP();
    cout<<(get(m+1)-get(n))<<endl;
    return 0;
}


你可能感兴趣的:(dp)