AcWing 1084. 數字遊戲 II

題目傳送門

題目描述

由於科協裏最近真的很流行數字遊戲。

某人又命名了一種取模數,這種數字必須滿足各位數字之和 mod N 爲 0。

現在大家又要玩遊戲了,指定一個整數閉區間 [a.b],問這個區間內有多少個取模數。

輸入格式

輸入包含多組測試數據,每組數據佔一行。
每組數據包含三個整數 a,b,N。

輸出格式

對於每個測試數據輸出一行結果,表示區間內各位數字和 mod N 爲 0 的數的個數。

數據範圍

1≤a,b≤231−1,
1≤N<100

輸入樣例:

1 19 9

輸出樣例:

2

解題思路:
樹形DP:
跟 數字遊戲 I 都是一個思路,只不過處理左分支的做法不同
f(i, j, k)表示當前有 i 位,最高位爲 j,且 % m 的餘數爲 k 的情況

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int N = 15;
int f[N][N][110];
int l, r, m;
int mod(int a, int b)  //防止出現負數
{
    return (a % b + b) % b;
}
void init()
{
    memset(f, 0, sizeof f);
    for(int i = 0; i <= 9; i++)f[1][i][i % m]++;
    for(int i = 2; i < N; i++)
        for(int j = 0; j <= 9; j++)
            for(int k = 0; k < m; k++)
                for(int x = 0; x <= 9; x++)
                    f[i][j][k] += f[i - 1][x][mod(k - j, m)];//等於i - 1位,最高位爲 x, 所有模數爲K - J的情況之和,
}
int dp(int n)
{
    if(n == 0)return 1;
    vector<int> nums;
    while(n)nums.push_back(n % 10), n /= 10;
    int res = 0;   //存答案
    int last = 0;  //存前面各位數字之和
    for(int i = nums.size() - 1; i >= 0; i--){
        int x = nums[i];
        for(int j = 0; j < x; j++)
            res += f[i + 1][j][mod(-last, m)];  //前面各位數的和爲last, (last + p) % m == 0 等同於(last - last) % m = 0,即模數爲-last
        last += x;
        if(i == 0 && last % m == 0)res++;//判斷最後一位的情況
    }
    return res;
}
int main()
{
    while(cin >> l >> r >> m){
        init();
        cout << dp(r) - dp(l - 1) << endl;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章