loj10165. 「一本通 5.3 例 3」Windy 数

Posted junk-yao-blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了loj10165. 「一本通 5.3 例 3」Windy 数相关的知识,希望对你有一定的参考价值。

思路:
  数位dp,设f[i][j]为以i为首元素, 长度为j, 的合题方案种数。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
const int maxn = 40;
long long f[maxn][maxn];
long long ppow10[maxn];
long long getws(long long x){
    for(int i = 18; i >= 0; --i){
        if(x >= ppow10[i])
            return i + 1;
    }
    return 1;
}
long long getxk(long long x, long long k){
    if(k > getws(x))    return 0;
    return (x / ppow10[k - 1]) % 10;
}
void init(){
    ppow10[0] = 1;
    for(long long i=1; i<=20; ++i)
        ppow10[i] = ppow10[i - 1] * 10;    
    for(int i=0; i<10; ++i)
        f[i][1] = 1;        
    for(long long j=2; j<=11; ++j)
        for(long long i=0; i<10; ++i)
            for(long long k = 0; k<10; ++k)
                if(k <= i - 2 || k >= i + 2)
                    f[i][j] += f[k][j-1];
}
long long DP(long long x, long long ws){
    long long ans = 0;
    for(long long i = 1; i < ws; ++i)
        for(long long j = 1; j < 10; ++j)
            ans += f[j][i];    
    for(long long i = 1; i < getxk(x, ws); ++i)
        ans += f[i][ws];            
    for(long long i = ws - 1; i >= 1; --i){
        for(long long j = 0; j < getxk(x, i); ++j)
            if(j <= getxk(x, i + 1) - 2 || j >= getxk(x, i + 1) + 2)
                ans += f[j][i];
        if(getxk(x, i) > getxk(x, i + 1) - 2 && getxk(x, i) < getxk(x, i + 1) + 2)
            return ans;        
    }
    return ans;        
}
int main(void)
{
    init();
    long long a, b;
    cin >> a >> b;
    cout << DP(b + 1, getws(b + 1)) - DP(a, getws(a)) << endl;
}

 


以上是关于loj10165. 「一本通 5.3 例 3」Windy 数的主要内容,如果未能解决你的问题,请参考以下文章

loj10147. 「一本通 5.1 例 1」石子合并

loj10043. 「一本通 2.2 例 1」剪花布条

loj10143. 「一本通 4.6 例 1」营业额统计

loj10193. 「一本通 6.1 例 1」序列的第 k 个数

AcWing 352/loj 10131. 「一本通 4.4 例 2」暗的连锁

「一本通 4.2 例 2」最敏捷的机器人(loj10120)