loj10166. 「一本通 5.3 练习 1」数字游戏

思路:

  设f[i][j]为i位数字,其和模N为j的方案种数,dp求解。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const long long maxn = 110;
long long f[maxn][maxn];
long long pow10[maxn];
long long a, b, N;
void init(){
    pow10[0] = 1;
    for(long long i = 1; i <= 20; ++i)
        pow10[i] = pow10[i-1] * 10;
    memset(f, 0, sizeof(f));    
    for(long long i = 0; i < 10; ++i)
        f[1][i % N]++;
    f[0][0] = 1;    
    for(long long i = 2; i < 20; ++i)
        for(long long j = 0; j < N; ++j)
            for(long long k = 0; k < 10; ++k)
                f[i][j] += f[i - 1][((N << 20) + j - k) % N];    
}

long long getws(long long x){
    for(long long i = 18; i >= 0; --i)
        if(x >= pow10[i])
            return i + 1;
    return 1;        
}
long long getxk(long long x, long long k){
    if(k > getws(x))    return 0;
    return (x / pow10[k-1]) % 10;
}
long long DP(long long x, long long ws){
    if(x == -1)    return 0;
    long long ans = 0, now = 0;
    for(long long i = ws; i >= 1; --i){
        for(long long j = getxk(x, i) - 1; j >= 0; --j)
            ans += f[i - 1][((N << 20) + 0 - j - now) % N];
        now += getxk(x, i);
    }
    long long sum = 0;
    for(long long i = ws; i >= 1; --i)
        sum += getxk(x, i);
    if(sum % N == 0)    ans++;            
    return ans;                
}
int main(void){
    while(cin >> a >> b >> N){
        init();
        cout << DP(b, getws(b)) - DP(a-1, getws(a - 1)) << endl;
    }
}

猜你喜欢

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