JZOJ 6809. [2020.10.29 Improve group simulation] No problem (acceptance + DP)

JZOJ 6809. [2020.10.29 Improve group simulation] No problem

Topic

  • Have KKK a1 - N 1-N1The arrangement of N , each time you can pick a queue to take the leader, but you can’t takeKKcontinuouslyK identical numbers, it is required to take out each interval[l, r] [l, r][l,r ] and cannot be taken out continuouslyr − l + 1 r-l+1rl+1 plan number of the same number.
  • N , K ≤ 300 N,K\leq 300 N,K300

answer

  • This question can be thought of as the number of plans that can only go to the right and upwards on the plane and require reaching a certain point and there are several points that cannot be passed.
  • You can use tolerance to set fi f_ifiIndicates that only the iiThe number of plans for i points that cannot be passed, subtract otherfj f_jfrom the total number ofplansfjI.e. fi f_ifi, Simply calculate the number of combinations.
  • This question is the same, but the dimension becomes KKK维, same samplefi f_ifiMeans only iii appears several times in a row, then you can enumeratefj f_jfjTransfer to fi f_ifi, Of course, it should be noted that here is not just the number of combinations, but first to reach each iiThe position of the previous i , and then multiply the factorial, the force isO (N 2 K 3) O(N^2K^3)O ( N2 K3 ), the intermediate calculation is simple and optimized to achieveO (N 2 K 2) O(N^2K^2)O ( N2 K2 ), still can't pass.
  • It is found that the title is stipulated to be random, that is, the larger the interval span, the less the amount that can be transferred, then directly violently record each transfer that can be transferred, and it can be passed.
  • Note that the right end of the interval is best to be from the left end + 1 +1+ 1 to start the enumeration, otherwise the constant may not pass, and the number of modulo operations can be minimized.

Code

#include<cstdio>
#include<queue>
using namespace std;
#define N 310
#define ll long long
#define md 1000000007
int a[N][N], p[N][N];
ll F[N * N], G[N * N], f[N];
int Sum[N][N], S[N][N], sum[N], s[N];
queue<int> q[N];
ll C(int x, int y) {
    
    
	return F[x] * G[y] % md * G[x - y] % md;
}
ll ksm(ll x, ll y) {
    
    
	if(!y) return 1;
	ll l = ksm(x, y / 2);
	if(y % 2) return l * l % md * x % md;
	return l * l % md;
}
int main() {
    
    
	int n, m, i, j, k, l, h, x;
	scanf("%d%d", &m, &n);
	F[0] = 1;
	for(i = 1; i < N * N; i++) F[i] = F[i - 1] * i % md;
	G[N * N - 1] = ksm(F[N * N - 1], md - 2);
	for(i = N * N - 2; i >= 0; i--) G[i] = G[i + 1] * (i + 1) % md;
	for(i = 1; i <= m; i++) {
    
    
		for(j = 1; j <= n; j++) {
    
    
			scanf("%d", &a[i][j]);
			p[i][a[i][j]] = j;
		}
		a[i][n + 1] = p[i][n + 1] = n + 1;
	}
	ll ans = 0, tot;
	for(i = 1; i < m; i++) {
    
    
		for(k = 1; k <= n + 1; k++) sum[k] = p[i][k] - 1, s[k] = 1;
		for(k = 1; k <= n + 1; k++)
			for(l = 1; l < k; l++) if(p[i + 1][a[i][l]] < p[i + 1][a[i][k]]) q[a[i][k]].push(a[i][l]), Sum[a[i][k]][a[i][l]] = k - l - 1, S[a[i][k]][a[i][l]] = 1;
		for(j = i + 1; j <= m; j++) {
    
    
			for(h = 1; h <= n + 1; h++) {
    
    
				k = a[i][h];
				s[k] = s[k] * C(sum[k] + p[j][k] - 1, sum[k]) % md;
				sum[k] += p[j][k] - 1;
				f[k] = s[k] * F[j - i + 1] % md;
				x = q[k].size(), tot = 0;
				while(x--) {
    
    
					l = q[k].front();
					q[k].pop();
					S[k][l] = S[k][l] * C(Sum[k][l] + p[j][k] - p[j][l] - 1, Sum[k][l]) % md;
					Sum[k][l] += p[j][k] - p[j][l] - 1;
					tot += f[l] * S[k][l] % md;
					if(p[j + 1][l] < p[j + 1][k]) q[k].push(l);
				}
				f[k] = (f[k] - tot % md * F[j - i + 1] % md + md) % md;
			}
			ans += f[n + 1] * G[j - i + 1] % md;
		}
	}
	printf("%lld\n", ans % md);
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_39565901/article/details/109426597