1. 程式人生 > 實用技巧 >Codeforces 1327E. Count The Blocks(組合計數)

Codeforces 1327E. Count The Blocks(組合計數)

連結:http://codeforces.com/contest/1327/problem/E
來源:Codeforces

  題意:給你一個 \(n\),如果 \(n = 3\),那麼一個數字的表示形式可以是 \(000,\) \(001,\) \(002,\) \(···,\) \(999\),現在給你一個 \(n\),如果是 \(000\),就算是一個長度為 \(3\) 的一個塊,如果是 \(001\),就有兩個塊,一個塊是長度為 \(2\) 的塊,另外一個塊是長度為 \(1\) 的塊,某一個數字如果連續出現 \(len\) 個,那麼就算是長度為 \(len\) 的塊,現在給你一個 \(n\),在 \([0, 10^{n} - 1]\)

,中我們可以找到多少個長度為 \(i\) 的塊。
  思路:如果 \(n = 1\) 的時候,那麼這一個位置我們可以放 [0, 9] 這 10 個數字,\(n = 2\) 的時候,如果 \(i == n\),那麼我們可以發現,我們只能在 10 個數字中選擇一個來填充這 n 個位置。如果 \(i < n\) 的時候,如果這個長度為 \(i\) 的塊,在這個數字的兩端,那麼在某一端可以選擇 \(10\) 個數字,在一端的旁邊我們只能選擇 \(9\) 個數字,這樣我們就可以保證這個數字中有長度為 \(i\) 的塊,那麼剩下的 \(n - i - 1\) 個位置,每一個位置我們都可以放 \(10\) 個數字,如果在左端是這種情況,那麼在右端也將是這種情況,此時這種情況的結果就是 \(10 * 9 * 10^{n - i - 1},n >= i + 1\)
;另外一種情況就是這個長度為 \(i\)的塊在整個數字的中間,中間一共有的數字就是 \(n - 2\) 個,這 \(n - 2\) 個位置我們可以組成的滿足條件的塊就是 \(n - 2 - i + 1\) 個,每一種情況都是可以選擇 \(10\) 個數字,在這個塊的兩端只能選擇 \(9\) 個數字,此時可以構造一個滿足條件的塊,此時的結果就是 \((n - 2 - i + 1) * 10 * 9 * 9\),這個時候還剩下的位置就是 \(n - i - 2\) 個,這裡每一個位置又可以選擇 \(10\) 個數字,這種情況下的結果就是 \(10 * 9 * 9 *(n - 2 - i + 1) * 10^{n - i - 2},n >= i + 2\)

# include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 2e5 + 10;
const int mod = 998244353;
int a[maxn];

ll quickPow(ll a, ll b) {
    ll ans = 1, res = a;
    while(b) {
        if(b & 1) ans = ans * res % mod;
        res = res * res % mod;
        b >>= 1;
    }
    return ans % mod;
}

int main() {
    int n; scanf("%d", &n);
    a[n] = 10;
    for(int i = 1; i <= n; ++ i) {
        if(n >= i + 1) a[i] = (1ll * 10 * 9 * quickPow(10, n - i - 1) % mod) * 2 % mod; 
        if(n >= i + 2) {
            a[i] +=  1ll * 10 * 9 * 9 * (n - 2 - i + 1) * quickPow(10, n - i - 2) % mod;
            a[i] %= mod;
        }
        //cout << i << " " << a[i] << "------------" << endl;
    }
    for(int i = 1; i <= n; ++ i) printf("%d%c", a[i], i == n ? '\n' : ' ');
    return 0;
}