luogu1758 [NOI2009] pipeline bead taking

Title Link

solution

We can turn the problem into two games, and finally output the same number of solutions.

Why can it be so transformed? We try to express this new problem with the formula. For a sequence \ (i \), if we get the number of his schemes in a game, it is \ (a_i \), then according to the multiplication principle, the number of his schemes in both games is \ (a_i^2 \), then the sum of all possible sequence schemes is \ (\ sum a_i^2 \).

What about this problem? We set the state \ (f[i][j][k][t] \) to indicate that \ (I \) balls are left in the first sequence, \ (j \) balls are left in the second sequence, \ (K \) balls are left in the first sequence, and \ (t \) solutions are left in the second sequence.
The final answer is \ (f[n][m][n][m] \).

Then consider the transition. For the state \ (f[i][j][k][t] \), I didn't enumerate the last ball added in each game. Then we can get the transfer equation as follows:

f[i][j][k][t]=f[i-1][j][k-1][t] + f[i-1][j][k][t-1]+f[i][j-1][k - 1][t]+f[i][j-1][k][t-1]

According to the definition of state, we can know that \ (i+j=k+t \) must be satisfied. So we only need to enumerate \ (i,j,k \) the third dimension to calculate the fourth dimension, without enumerating the fourth dimension. The space-time complexity is \ (O(n^3) \).

Time is OK, but space will explode. So just scroll the first dimension.

code

/*
* @Author: wxyww
* @Date:   2020-05-28 14:57:30
* @Last Modified time: 2020-05-28 16:07:27
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
#include<cmath>
using namespace std;
typedef long long ll;
const int N = 510,mod = 1024523;
ll read() {
	ll x = 0,f = 1;char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-') f = -1; c = getchar();
	}
	while(c >= '0' && c <= '9') {
		x = x * 10 + c - '0'; c = getchar();
	}
	return x * f;
}
int f[2][N][N];
char s[N],t[N];
int main() {
	int n = read(),m = read();
	scanf("%s",s + 1);
	scanf("%s",t + 1);

	f[0][0][0] = 1;
	for(int i = 0;i <= n;++i) {
		int tmp = i & 1;
		for(int j = 0;j <= m;++j) {
			for(int k = 0;k <= min(n,i + j);++k) {
				if(!i && !j && !k) {f[tmp][j][k] = 1;continue;}
				f[tmp][j][k] =  0;
				int tt = i + j - k;
				if(i && k && s[i] == s[k]) {
					f[tmp][j][k] += f[tmp ^ 1][j][k - 1];
					f[tmp][j][k] >= mod ? f[tmp][j][k] -= mod : 0;
				}
				if(i && tt && s[i] == t[tt]) {
					f[tmp][j][k] += f[tmp ^ 1][j][k];
					f[tmp][j][k] >= mod ? f[tmp][j][k] -= mod : 0;
				}
				if(j && k && t[j] == s[k]) {
					f[tmp][j][k] += f[tmp][j - 1][k - 1];
					f[tmp][j][k] >= mod ? f[tmp][j][k] -= mod : 0;
				}
				if(j && tt && t[j] == t[tt]) {
					f[tmp][j][k] += f[tmp][j - 1][k];
					f[tmp][j][k] >= mod ? f[tmp][j][k] -= mod : 0;
				}
			}
		}
	}

	cout<<f[n & 1][m][n]<<endl;
	return 0;
}

Tags: C++

Posted on Thu, 28 May 2020 10:33:42 -0400 by manmanman