这里补一下E题
解题思路:
- 这题自己没写出来,主要是不知道组合的板子
- 首先正常来推理思路
- 有n个点,m种颜色,然后最多有k个相邻点可以使颜色相同
- 那么对于k我们就可以分解成0 - k ,k + 1种情况
- 对于任何一个i (0 ~ k),我们都有
ans = m * C(n - 1,i) * (m - 1) ^ (n - i - 1)
- 这里的m是第一个位置选颜色的个数,那么后面的位都可以选用(m - 1) 个颜色,其中有i个位置的颜色与相邻相同,所以我们选出这i个位置,其他的就有n - i - 1个位置 (那个 1 是第一位占用的),然后根据这个式子,就可以求出(这里的m可以提出)。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int mod = 998244353, N = 200010;
ll fac[N], p[N];
ll inv[N];
ll mod_mult(ll a,ll b,ll m){ //计算 a*b
ll res = 0;
ll exp = a % m;
while(b){
if (b&1){
res += exp;
if (res > m) res -= m;
}
exp<<=1;
if (exp > m) exp -= m;
b>>=1;
}
return res;
}
ll mod_exp(ll a,ll b,ll m){
ll res = 1;
ll exp = a % m;
while(b){
if (b & 1) res = mod_mult(res,exp,m);
exp = mod_mult(exp,exp,m);
b>>=1;
}
return res;
}
ll C(int x, int y){
return fac[x]*inv[y]%mod*inv[x-y]%mod;
}
int main(){
long long n, m, k;
scanf("%lld%lld%lld",&n,&m,&k);
long long ans = 0;
fac[0] = 1;
for (int i = 1; i <= n; i++) fac[i] = 1ll * fac[i - 1] * i % mod;
inv[n] = mod_exp(fac[n], mod - 2, mod);
for (int i = n ; i >= 0; i--) inv[i - 1] = 1ll * inv[i] * i % mod;
p[0] = 1;
for (int i = 1; i <= n; i++){
p[i] = p[i - 1] * (m - 1) %mod;
}
for (int i = 0; i <= k; i++){
long long num = C(n-1,i) % mod * p[n - i - 1] % mod;
ans = (ans + num) % mod;
}
printf("%lld\n",ans * m % mod);
return 0;
}