제출 #1323913

#제출 시각아이디문제언어결과실행 시간메모리
1323913Jawad_Akbar_JJ힘 센 거북 (IZhO11_turtle)C++20
55 / 100
136 ms28616 KiB
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
#define int long long
const int N = 600005, KK = 25;
int fac[10][N], inv[10][N], Pre[10][N];
vector<int> pw[10];
int dp[KK][KK], dp2[KK][KK], fdp[KK][KK];

void euclid(int a, int b, int &x, int &y){
	if (!b){
		x = 1, y = 0;
		return;
	}
	euclid(b, a % b, y, x);
	y -= (a / b) * x;
}

int CRT(int a, int b, int m1, int m2, int x = 0, int y = 0){
	euclid(m1, m2, x, y);

	int X = b * x * m1 + a * y * m2;
	X %= (m1 * m2);
	if (X < 0)
		X += m1 * m2;
	return X;
}

int power(int a, int b, int M){
	int ans = 1, pr = a;
	for (; b; b >>= 1){
		if (b & 1)
			ans = ans * pr % M;
		pr = pr * pr % M;
	}
	return ans;
}

int choose(int id, int n, int k, int M, int c){
	int r = Pre[id][n] - Pre[id][k] - Pre[id][n - k];
	if (r >= c)
		return 0;
	int ans = fac[id][n] * inv[id][k] % M * inv[id][n - k] % M * pw[id][r] % M;
	// cout<<n<<" "<<k<<" "<<fac[id][n]<<" "<<inv[id][k]<<" "<<inv[id][n - k]<<" "<<pw[id][r]<<" "<<M<<" "<<ans<<'\n';
	return ans;
}

vector<pair<int, int>> trp, prms;

signed main(){
	int n, m, k, T, Z, id = 0, Mod;
	cin>>n>>m>>k>>T>>Z, Mod = Z;

	trp = {{0, 0}, {n, m}};
	for (int i=1, x, y;i<=k;i++){
		cin>>x>>y;
		trp.push_back({x, y});
	}
	sort(begin(trp), end(trp));

	for (int p=2;p * p <= Z;p++){
		int c = 0, pk = 1;
		while (Z % p == 0)
			Z /= p, c++, pk = pk * p;
		if (c)
			prms.push_back({p, c});
	}
	if (Z - 1)
		prms.push_back({Z, 1});

	for (int i=0;i<prms.size();i++){
		for (int j=0, p = 1;j<30;j++, p *= prms[i].first)
			pw[i].push_back(p);
	}

	for (int j=0;j<prms.size();j++){
		auto [p, k] = prms[j];
		int pk = pw[j][k], tot = (pk / p) * (p - 1);

		fac[j][0] = inv[j][0] = 1;
		for (int i=1, I;i<N;i++){
			I = i, Pre[j][i] = Pre[j][i-1];
			while (I % p == 0)
				I /= p, Pre[j][i]++;

			fac[j][i] = fac[j][i-1] * I % pk;

			inv[j][i] = power(fac[j][i], tot - 1, pk);
			// if (i <= 10)
			// 	cout<<j<<" "<<i<<" "<<fac[j][i]<<" "<<inv[j][i]<<'\n';
		}
		id++;
		// cout<<p<<" "<<k<<" "<<pk<<endl;
	}
	// cout<<"done"<<endl;

	for (int i=0;i<k+2;i++){
		for (int j=0;j<k+2;j++){
			int X = trp[j].first - trp[i].first, Y = trp[j].second - trp[i].second, A, M = 0, a, m;
			if (X < 0 or Y < 0)
				continue;
			// cout<<i<<" "<<j<<endl;

			for (int l=0;l<id;l++){
				auto [p, k] = prms[l];
				// cout<<l<<endl;
				m = pw[l][k], a = choose(l, X + Y, Y, m, k);
				// cout<<"    "<<m<<" "<<a<<endl;
				// cout<<l<<endl;
				if (M == 0)
					M = m, A = a;
				else
					A = CRT(A, a, M, m), M = M * m;
			}
			dp[i][j] = A;
			// cout<<i<<" "<<j<<" "<<dp[i][j]<<'\n';
			// cout<<i<<" "<<j<<endl;
		}
	}
	// cout<<"done"<<endl;
	for (int i=0;i<k+2;i++){
		for (int j=0;j<k+2;j++){
			if (!dp[i][j])
				continue;
			dp2[i][j] = dp[i][j];
			for (int l=i+1;l<j;l++){
				dp2[i][j] = (dp2[i][j] - dp2[i][l] * dp[l][j]) % Z;
				if (dp2[i][j] < Z)
					dp2[i][j] += Z;
			}
			// cout<<i<<" "<<j<<" "<<dp[i][j]<<" "<<dp2[i][j]<<'\n';
		}
	}
	fdp[0][0] = 1;
	for (int i=1;i<k+2;i++){
		for (int j=0;j<i;j++)
			for (int t=0;t<=T;t++)
				fdp[i][t+1] = (fdp[i][t+1] + fdp[j][t] * dp2[j][i]) % Mod;

	}

	int Ans = 0;
	for (int t=0;t<=T+1;t++)
		Ans = (Ans + fdp[k+1][t]) % Mod;
	cout<<Ans<<'\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...