1. 程式人生 > 其它 >21.7.8 t2

21.7.8 t2

tag:組合計數


顯然出題人直接把兩個問題直接拼了起來。。

可以列舉放了 \(i\)\(2\),則有 \(n-2i\)\(1\),且序列長度為 \(n-i\)

然後第二問只與 \(len\) 有關,原問題是先塗色再選點,實際上可以先選點再塗色。選出來的點一定是黑白交錯,而且對應唯一的一種塗色方案。

規定了選擇 \(s\) 個黑點,那麼白點有 \(len-s\) 個,然後規定最後一個一定是白色。

所以就是 \(\binom{len-1}{2(len-s)-1}\)


#include<bits/stdc++.h>
using namespace std;

template<typename T>
inline void Read(T &n){
	char ch; bool flag=false;
	while(!isdigit(ch=getchar()))if(ch=='-')flag=true;
	for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
	if(flag)n=-n;
}

enum{
    MAXN = 10000005,
    MOD = 998244353
};

inline int ksm(int base, int k=MOD-2){
    int res=1;
    while(k){
        if(k&1)
            res = 1ll*res*base%MOD;
        base = 1ll*base*base%MOD;
        k >>= 1;
    }
    return res;
}

int pw1[MAXN], pw2[MAXN];
int n, s, ans;

int jc[MAXN<<1], invjc[MAXN<<1];
inline int C(int n, int m){return (n<m or m<0)?0:1ll*jc[n]*invjc[m]%MOD*invjc[n-m]%MOD;}
inline int calc(int len){return C(len-1,2*(len-s)-1);}

inline void prework(int n){
    jc[0] = 1; for(int i=1; i<=n; i++) jc[i] = 1ll*jc[i-1]*i%MOD;
    invjc[n] = ksm(jc[n]); for(int i=n; i; i--) invjc[i-1] = 1ll*invjc[i]*i%MOD;
}

int main(){
    Read(n); Read(pw1[1]); Read(pw2[1]); Read(s);
    prework(n<<1);
    pw1[0] = pw2[0] = 1;
    for(int i=2; i<=n; i++) 
        pw1[i] = 1ll*pw1[i-1]*pw1[1]%MOD,
        pw2[i] = 1ll*pw2[i-1]*pw2[1]%MOD;
    for(int i=0; i<=n/2; i++)
        // printf("calc(%d) = %d\n",n-i,calc(n-i)),
        ans = (ans+1ll*calc(n-i)*C(n-i,i)%MOD*pw1[n-2*i]%MOD*pw2[i])%MOD;
    cout<<ans<<'\n';
}