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