1327E Count The Blocks(組合數學)
題意: 對於一個數字串 ,可以看做是由多個連續相同的數字塊組成的,比如 ,其長度爲 的數字塊有兩個(、),長度爲 的數字塊有一個(),長度爲 的數字塊有 個(、、)。現在給整數 ,表示有 到 共 個數字,現在要求這些數字中長度爲 的數字塊的個數,答案對 取模。
範圍:
分析:直接枚舉所有的數字進行統計肯定是不行的,根據數據範圍應該需要對每種長度的數字塊,通過公式計算出其數量。
因爲數字塊是連續相同的數字,因此可以直接看做是一個點。比如當前 ,相當於 ,總方案數爲 (),對應 ()。若當前 ,相當於 …因此這些問題都可以轉換成 的情況。
那麼我們只要求當 的答案。
例如 。
① 這個點在第一位,那麼方案數爲
② 這個點在第二位,那麼方案數爲
③ 這個點在第三位,那麼方案數爲
④ 這個點在第四位,那麼方案數爲
我們可以發現除了兩端的點,中間位置的方案數都相同,可以只計算一次。
對於中間位置的點,該點的數字方案有 種,與之相鄰的兩個點方案數爲 ,其餘點的方案數爲 ,故方案數爲 ,而中間位置的點有 個,所以中間所有位置的總方案爲 。
對於兩端的點,該點的數字方案有 種,與之相鄰的一個點方案數爲 ,其餘點的方案數爲 ,故方案數爲 ,有左右兩個端點,所有總方案數爲 。
因此,對於所有的長度 ,我們都可以用上述的公式在 的時間內算出其方案數,總體時間複雜度爲 。
Code:
#include <bits/stdc++.h>
#define int long long
#define double long double
using namespace std;
const int MAXN = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 998244353;
const double eps = 1e-9;
const double PI = acos(-1.0);
int n;
inline int read()
{
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
int num[MAXN];
signed main()
{
// 預處理一下,也可以不預處理
num[0] = 1;
for (int i = 1; i < MAXN; i++)
{
num[i] = num[i - 1] % MOD * 10 % MOD;
}
n = read();
for (int i = 1; i <= n; i++)
{
if (i > 1)
cout << " ";
int len = n - i + 1; // 區間縮點後總點數
int ans;
// 2個點以上套公式
if (len >= 2)
{
ans = (len - 2) % MOD * 81 % MOD * num[len - 2] % MOD + 18 * num[len - 1] % MOD;
}
// 1個點只有10種方案數
else
{
ans = 10;
}
cout << ans % MOD;
}
cout << endl;
return 0;
}
【END】感謝觀看