AtCoder Beginner Contest 167

这里补一下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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章