[SCOI2009]windy数 数位dp

Code:

#include<cmath>
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=30;
long long f[maxn][12];
void get_table(){
    for(int i=0;i<=9;++i)f[1][i]=1;	
    for(int i = 2 ; i <= 13 ; ++i) 
        for(int j = 0; j <= 9; ++j)
            for(int last = 0; last <= 9; ++last) 
            if(abs(j-last)>=2)f[i][j]+=f[i-1][last];
}
int get_length(long long num){
    int cnt=1;
    while(num/=10)++cnt;
    return cnt;
}
long long get_mod(int length){
    long long res=1;
    for(int i=1;i<length;++i)res*=10;
    return res;
}
long long g(long long num,int length,int cur){
    long long mod=get_mod(length);                   
    int current=num/mod;      
    num-=(current*mod);   
    if(cur>current)return 0;                    
    if(cur<current||length==1)return f[length][cur];   
    if(num==0){
        if(length==2&&abs(current)>=2)return 1;                 //2 digit number
        return 0;
    }
    long long fin=0;
    for(int i=0;i<=9;++i)
        if(abs(i-cur)>=2)fin+=g(num,length-1,i);
    return fin;
}
long long solve(long long num){
    int length=get_length(num);
    long long mod=get_mod(length);
    long long fin=1;
    if(num==-1)return 0;
    if(length==1)return 1;
    for(int i=length-1;i>=1;--i)
        for(int j=1;j<=9;++j)fin+=f[i][j];
    int head=num/mod;
    for(int i=1;i<head;++i)fin+=f[length][i];
    long long h=g(num,length,head);
    return fin+h;
}
int main()
{
    
    get_table();
    long long a,b;
    cin>>a>>b;
    long long st=solve(a-1);
    long long ed=solve(b);
    cout<<ed-st;
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/9871151.html