kmjp's blog

競技プログラミング参加記です

yukicoder : No.2582 Random Average^K

こういう式変形苦手…。
https://yukicoder.me/problems/no/2582

問題

N個の[0,1]の範囲を取る変数がある。それぞれの確率は一様分布である。
これらN個の変数の相加平均のK乗の期待値を求めよ。

解法

各変数をt1,t2....tNとすると、求めたい値は \displaystyle \int_{[0,1]^N}\left(\frac{t_1+t_2+...+t_N}{N}\right)^K dt_1dt_2...dt_Nである。
右辺を式変形すると、 \displaystyle \frac{K!}{(N+K)!N^K}\sum_k C(N,k)(-1)^{N-k}k^{N+K}となる。
これらは二項係数と整数の累乗が計算できれば高速に計算できる。

int N,K;
const ll mo=998244353;

const int NUM_=2000003;
static ll fact[NUM_+1],factr[NUM_+1],inv[NUM_+1];

ll modpow(ll a, ll n = mo-2) {
	ll r=1;a%=mo;
	while(n) r=r*((n%2)?a:1)%mo,a=a*a%mo,n>>=1;
	return r;
}


void solve() {
	int i,j,k,l,r,x,y; string s;
	
	inv[1]=fact[0]=factr[0]=1;
	for (int i=2;i<=NUM_;++i) inv[i] = inv[mo % i] * (mo - mo / i) % mo;
	for (int i=1;i<=NUM_;++i) fact[i]=fact[i-1]*i%mo, factr[i]=factr[i-1]*inv[i]%mo;
	
	cin>>N>>K;
	ll ret=0;
	for(i=0;i<=N;i++) {
		ll a=fact[N]*factr[i]%mo*factr[N-i]%mo*modpow(i,N+K)%mo;
		if((N-i)%2) {
			ret+=mo-a;
		}
		else {
			ret+=a;
		}
	}
	ret%=mo;
	
	for(i=1;i<=K;i++) ret=ret*i%mo;
	ll a=1;
	for(i=1;i<=K+N;i++) a=a*i%mo;
	ret=ret*modpow(a)%mo*modpow(modpow(N,K))%mo;
	cout<<ret<<endl;
	
	
}

まとめ

こういう式変形何やれば慣れるんだろうな。