[NOI2019] bucket main land [Lagrange interpolation, finding rules, combinatorial mathematics]

Posted by bogdan on Mon, 21 Oct 2019 23:50:22 +0200

Portal

First of all, there is a 30 point method of violence. Let f[i][j] be or i, j probability.

Then v[i] is the current sequence

Then you will find out that it's an isochromatic when type = 1, and a second-order isochromatic when type = 2.

That is to say, we only need to maintain the first three items, and then insert the last one violently.

Each time we divide into A and n - A piles, we need to insert the values of A+1,A+2, A+3, and then solve the current first three items similar to the above v

Now the only problem is the f array. Obviously, it can't be processed by n^2.

We found that the numerator and denominator are determined.

Denominator is

The molecule is

Then the two stacks are taken as a combination number.

30 pts

#include<bits/stdc++.h>
#define N 105
using namespace std;
typedef long long ll;
int read(){
	int cnt = 0, f = 1; char ch = 0;
	while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1;}
	while(isdigit(ch)) cnt = (cnt << 1) + (cnt << 3) + (ch-'0'), ch = getchar();
	return cnt * f;
}
const int Mod = 998244353;
int n, m, type;
ll f[N][N], v[N], a[N], b[N];
ll add(ll a, ll b){ return (a+b) % Mod;}
ll mul(ll a, ll b){ return (a*b) % Mod;}
ll power(ll a, ll b){
	ll ans = 1;
	for(;b;b>>=1){
		if(b&1) ans = mul(ans, a);
		a = mul(a, a);
	} return ans;
}
int main(){
	n = read(), m = read(), type = read();
	for(int i=1; i<=n; i++) v[i] = (type == 1 ? i : mul(i, i));
	for(int Case=1; Case<=m; Case++){
		int A = read(); 
		for(int i=1; i<=A; i++) a[i] = v[i];
		for(int i=1; i<=n-A; i++) b[i] = v[i + A];
		memset(f, 0, sizeof(f));
		f[A][n-A] = 1;
		for(int i=A; i>=0; i--){
			for(int j=n-A; j>=0; j--){
				ll inv = power(i + j, Mod - 2);
				if(i) f[i-1][j] = add(f[i-1][j], mul(f[i][j], mul(inv, i)));
				if(j) f[i][j-1] = add(f[i][j-1], mul(f[i][j], mul(inv, j)));
			}
		} memset(v, 0, sizeof(v));
		for(int i=n; i>=1; i--){
			ll inv = power(i, Mod - 2);
			for(int j=min(i, A); j>=0; j--){
				int k = i - j; if(k > n - A) break;
				if(j) v[i] = add(v[i], mul(f[j][k], mul(a[j], mul(inv, j))));
				if(k) v[i] = add(v[i], mul(f[j][k], mul(b[k], mul(inv, k))));
			}
		}
	}
	int q = read();
	for(int i=1; i<=q; i++){
		int x = read(); printf("%lld\n", v[x]);
	} return 0;
}

100 pts

#include<bits/stdc++.h>
#define N 10000050
using namespace std;
typedef long long ll;
int read(){
	int cnt = 0, f = 1; char ch = 0;
	while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1;}
	while(isdigit(ch)) cnt = (cnt << 1) + (cnt << 3) + (ch-'0'), ch = getchar();
	return cnt * f;
}
const int Mod = 998244353;
int n, m, type;
ll add(ll a, ll b){ return (a+b) % Mod;}
ll mul(ll a, ll b){ return (a*b) % Mod;}
ll power(ll a, ll b){
	ll ans = 1;
	for(;b;b>>=1){
		if(b&1) ans = mul(ans, a);
		a = mul(a, a);
	} return ans;
}
ll fac[N], inv[N];
void prework(){
	fac[0] = fac[1] = inv[0] = inv[1] = 1;
	for(int i=2; i<=n; i++) fac[i] = mul(fac[i-1], i);
	inv[n] = power(fac[n], Mod - 2);
	for(int i=n-1; i>=2; i--) inv[i] = mul(inv[i+1], i+1);
}
ll f[5], g[5], h[5], pre[5], suf[5];
ll C(int n, int m){ return mul(fac[n], mul(inv[n-m], inv[m]));}
ll Get(int A, int B, int i, int j){
	if(A < i || B < j) return 0;
	ll ans = power(mul(fac[A + B], inv[i + j]), Mod - 2);
	ans = mul(ans, C(A + B - i - j, A - i));
	ans = mul(ans, mul(mul(fac[A], inv[i]), mul(fac[B], inv[j])));
	return ans;
}
const int up = 3;
ll lagrange(ll *y, int n){
	if(n <= up) return y[n]; pre[0] = suf[up + 1] = 1;
	for(int i=1; i<=up; i++) pre[i] = mul(pre[i-1], n - i);
	for(int i=up; i>=1; i--) suf[i] = mul(suf[i+1], n - i);
	ll ans = 0;
	for(int i=1; i<=up; i++){
		ll tmp = mul(y[i], mul(mul(inv[i-1], inv[up-i]), mul(pre[i-1], suf[i+1])));
		ans = ((up - i) & 1) ? add(ans, Mod - tmp) : add(ans, tmp);
	} return ans;
}
int main(){
	freopen("landlords.in","r",stdin);
	freopen("landlords.out","w",stdout);
	n = read(), m = read(), type = read(); prework();
	for(int i=1; i<=3; i++) f[i] = (type == 1 ? i : mul(i, i));
	for(int Case = 1; Case <= m; Case ++){
		int A = read();
		swap(f, g);
		for(int i=1; i<=3; i++) h[i] = lagrange(g, A + i);
		memset(f, 0, sizeof(f));
		for(int i=0; i<=3; i++){
			for(int j=0; i+j <= 3; j++){
				if(i + j == 0) continue;
				ll tmp = Get(A, n - A, i, j);
				ll inv = power(i + j, Mod - 2);
				f[i + j] = add(f[i + j], mul(tmp, mul(g[i], mul(i, inv))));
				f[i + j] = add(f[i + j], mul(tmp, mul(h[j], mul(j, inv))));
			}
		}
	}
	int q = read();
	while(q--){
		int x = read(); printf("%lld\n", lagrange(f, x));
	} return 0;
}