吐槽請無視
哇塞我終於開始更博客了!感不感動!興不興奮!%¥#%$#@*&....
emm事實上是因爲csdn的LaTeX終於修復好了。。
ps.
之後的題解可能都會相對簡略。
並且養成標題上加算法的好習慣,,
題意:
維護一個集合,初始有兩個數 。
進行 次操作,每次隨機選一個數,把它減一;如果結果爲 ,把它刪掉;否則,如果集合大小不超過 ,則添一個 。
最後問那個 期望被減了多少。
詢問 的次數 (極限數據爲 ), 。
做法:
定義 表示第 輪,血量爲1/2/3的分別剩下 個奴隸主,此時的期望次數;將所有合法 的狀態找出來發現最多165種,於是重新定義, 表示第 輪,狀態爲 的期望次數, 。用矩陣快速冪優化這個dp。
然後每個詢問重新計算很慢,於是先 預處理,複雜度 。
加一些卡常優化,,諸如開個大模數減少模的次數。
代碼:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 10;
const int M = 170;
const int mod = 998244353;
const ll lim = (0x7fffffffffffffffll/mod-mod)*mod;
int m, K, tot, id[N][N][N];
ll n;
ll inv[N], tmp[M], ans[M];
inline ll ksm(ll x, ll p) {
ll ret = 1;
for(; p; p >>= 1, x = x*x%mod) if(p&1) ret = ret*x%mod;
return ret;
}
struct matrix {
ll s[M][M];
matrix() { memset(s, 0, sizeof s); }
} a[65];
inline matrix sqr(const matrix &x) {
matrix ret;
for(int i = 1; i <= tot+1; i ++)
for(int j = 1; j <= tot+1; j ++) {
for(int k = 1; k <= tot+1; k ++) {
ret.s[i][j] += x.s[i][k]*x.s[k][j];
if(ret.s[i][j] >= lim) ret.s[i][j] -= lim;
}
ret.s[i][j] %= mod;
}
return ret;
}
inline void mul(const matrix &x) {
memset(tmp, 0, sizeof tmp);
for(int i = 1; i <= tot+1; i ++) {
for(int j = 1; j <= tot+1; j ++) {
tmp[i] += ans[j]*x.s[j][i];
if(tmp[i] >= lim) tmp[i] -= lim;
}
tmp[i] %= mod;
}
for(int i = 1; i <= tot+1; i ++) ans[i] = tmp[i];
}
int main() {
int test;
scanf("%d%d%d", &test, &m, &K);
for(int i = 0; i <= K; i ++)
for(int j = 0; j <= ((m>1)?K-i:0); j ++)
for(int k = 0; k <= ((m>2)?K-i-j:0); k ++) id[i][j][k] = ++ tot;
for(int i = 0; i <= K+1; i ++) inv[i] = ksm(i, mod-2);
for(int i = 0; i <= K; i ++)
for(int j = 0; j <= ((m>1)?K-i:0); j ++)
for(int k = 0; k <= ((m>2)?K-i-j:0); k ++) {
int now = id[i][j][k], nk = (i+j+k)<K; ll iv = inv[i+j+k+1];
if(m >= 1) if(i) a[0].s[now][id[i-1][j][k]] = iv*i%mod;
if(m >= 2) {
if(m == 2) if(j) a[0].s[now][id[i+1][j-1+nk][k]] = iv*j%mod;
if(m == 3) if(j) a[0].s[now][id[i+1][j-1][k+nk]] = iv*j%mod;
}
if(m >= 3) if(k) a[0].s[now][id[i][j+1][k-1+nk]] = iv*k%mod;
a[0].s[now][now] = a[0].s[now][tot+1] = iv;
}
a[0].s[tot+1][tot+1] = 1;
for(int i = 1; i <= 63; i ++) a[i] = sqr(a[i-1]);
while(test --) {
scanf("%lld", &n);
memset(ans, 0, sizeof ans);
if(m == 1) ans[id[1][0][0]] = 1;
if(m == 2) ans[id[0][1][0]] = 1;
if(m == 3) ans[id[0][0][1]] = 1;
for(int i = 0; n; n >>= 1, i ++) if(n&1) mul(a[i]);
printf("%lld\n", ans[tot+1]);
}
return 0;
}