loj10164. 「一本通 5.3 例 2」数字游戏

思路:
  既然是数位dp,先写两个函数分别求一个十进制数值的指定位和该数的位数。

  设f[i][j]为用i个数字单调不降地填满j个位置,初始化f[i][0]=1(i从1到10),转移方程f[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 0;
}
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(long long i=1; i<=10; ++i)
        f[i][0] = 1;
    for(long long j=1; j<=32; ++j)
        for(long long i=1; i<=10; ++i)
            for(long long k = 1; k<=i; ++k)
                f[i][j] += f[k][j-1];
}
long long DP(long long x, long long ws){
    long long ans = 0;
    for(long long i = ws; i >= 1; --i){
        for(long long j = getxk(x, i + 1); j < getxk(x, i); ++j)
            ans += f[10 - j][i - 1];
        if(getxk(x, i) < getxk(x, i + 1))
            return ans;
    }    
    if(getxk(x, 1) >= getxk(x, 2))
        ans++;
    return ans;        
}
int main(void)
{
    init();
    long long a, b;
    while(cin >> a >> b){
        cout << DP(b, getws(b)) - DP(a - 1, getws(a - 1))<< endl;
    }
}

猜你喜欢

转载自www.cnblogs.com/junk-yao-blog/p/9495100.html