【CodeForces506E】Mr. Kitayuta's Gift

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/84337693

【题目链接】

【思路要点】

  • 首先有一个简单的 O(S3+NS2)O(|S|^3+N*|S|^2)dpdp 做法,即从结果串的两边向中间 dpdp
  • 这个方法同样可以对于所有 MNM≤N 算出所有答案。
  • 由数据范围,本题的正解很可能是矩阵乘法优化 dpdp ,不妨用上述 dpdp 计算较小范围的答案,然后尝试用 BerlekampMasseyBerlekamp-Massey 算法 解出答案的递推式。
  • 经尝试,答案存在一个不超过 3S+53|S|+5 阶的线性递推式。
  • CayleyHamiltonCayley-Hamilton 定理 优化递推即可。
  • 时间复杂度 O(S3+S2LogN)O(|S|^3+|S|^2LogN)

【代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 205;
const int P = 1e4 + 7;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
template <typename T> void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
	write(x);
	puts("");
}
void update(int &x, int y) {
	x += y;
	if (x >= P) x -= P;
}
namespace LinearSequence {
	const int MAXN = 1205;
	int cnt, delta[MAXN], fail[MAXN];
	int k, h[MAXN], r[MAXN];
	vector <int> a[MAXN];
	int power(int x, int y) {
		if (y == 0) return 1;
		int tmp = power(x, y / 2);
		if (y % 2 == 0) return tmp * tmp % P;
		else return tmp * tmp % P * x % P;
	}
	void times(int *a, int *b, int *res) {
		static int tmp[MAXN];
		memset(tmp, 0, sizeof(tmp));
		for (int i = 0; i <= k - 1; i++)
		for (int j = 0; j <= k - 1; j++)
			update(tmp[i + j], a[i] * b[j] % P);
		for (int i = 2 * k - 1; i >= k; i--) {
			int val = tmp[i];
			for (int j = 1; j <= k; j++)
				update(tmp[i - j], val * r[j] % P);
		}
		for (int i = 0; i <= k - 1; i++)
			res[i] = tmp[i];
	}
	int getans(int n) {
		if (n <= k) return h[n];
		static int tmp[MAXN], res[MAXN];
		memset(tmp, 0, sizeof(tmp));
		memset(res, 0, sizeof(res));
		n -= k, res[0] = 1, tmp[1] = 1;
		for (int bit = 1; n != 0; bit <<= 1) {
			if (bit & n) {
				n ^= bit;
				times(res, tmp, res);
			}
			times(tmp, tmp, tmp);
		}
		int ans = 0;
		for (int i = 0; i <= k - 1; i++)
			update(ans, res[i] * h[i + k] % P);
		return ans;
	}
	void work(int given, int *val, int n) {
		a[cnt = 0].clear();
		for (int i = 1; i <= given; i++) {
			delta[i] = val[i];
			for (unsigned j = 0; j < a[cnt].size(); j++)
				update(delta[i], P - a[cnt][j] * val[i - j - 1] % P);
			if (delta[i] == 0) continue;
			fail[cnt] = i;
			if (cnt == 0) {
				a[++cnt].clear();
				a[cnt].resize(i);
				continue;
			}
			int mul = delta[i] * power(delta[fail[cnt - 1]], P - 2) % P;
			a[cnt + 1].clear(), a[cnt + 1].resize(i - fail[cnt - 1] - 1);
			a[cnt + 1].push_back(mul);
			for (unsigned i = 0; i < a[cnt - 1].size(); i++)
				a[cnt + 1].push_back((P - a[cnt - 1][i]) * mul % P);
			a[cnt + 1].resize(max(a[cnt + 1].size(), a[cnt].size()));
			for (unsigned i = 0; i < a[cnt].size(); i++)
				update(a[cnt + 1][i], a[cnt][i]);
			cnt++;
		}
		k = a[cnt].size();
		for (int i = 1; i <= 2 * k; i++)
			h[i] = val[i];
		for (int i = 1; i <= k; i++)
			r[i] = a[cnt][i - 1];
		writeln(getans(n));
	}
}
char s[MAXN];
int len, n, ans[MAXN * 8], done[MAXN * 4];
int dp[MAXN * 4][MAXN][MAXN];
int main() {
	scanf("%s", s + 1);
	len = strlen(s + 1), read(n);
	dp[0][1][len] = 1;
	for (int k = 1; k <= len * 4 + 5; k++) {
		done[k] = done[k - 1] * 26 % P;
		for (int i = 1; i <= len; i++)
		for (int j = i; j <= len; j++) {
			if (s[i] == s[j]) {
				if (i + 1 <= j - 1) update(dp[k][i + 1][j - 1], dp[k - 1][i][j]);
				else update(done[k], dp[k - 1][i][j]);
				update(dp[k][i][j], dp[k - 1][i][j] * 25 % P);
			} else {
				if (i == j) update(done[k], dp[k - 1][i][j] * 2 % P);
				else {
					update(dp[k][i + 1][j], dp[k - 1][i][j]);
					update(dp[k][i][j - 1], dp[k - 1][i][j]);
				}
				update(dp[k][i][j], dp[k - 1][i][j] * 24 % P);
			}
		}
	}
	for (int i = 1; i <= len * 8 + 5; i++) {
		if (i & 1) {
			ans[i] = done[i / 2] * 26 % P;
			for (int j = 1; j <= len; j++)
				update(ans[i], dp[i / 2][j][j]);
		} else ans[i] = done[i / 2];
	}
	LinearSequence :: work(len * 7 + 5, ans + len, n);
	return 0;
}
阅读更多

Mr. Young's Picture Permutations

10-15

DescriptionnnMr. Young wishes to take a picture of his class. The students will stand in rows with each row no longer than the row behind it and the left ends of the rows aligned. For instance, 12 students could be arranged in rows (from back to front) of 5, 3, 3 and 1 students. nX X X X XnnX X XnnX X XnnXnnIn addition, Mr. Young wants the students in each row arranged so that heights decrease from left to right. Also, student heights should decrease from the back to the front. Thinking about it, Mr. Young sees that for the 12-student example, there are at least two ways to arrange the students (with 1 as the tallest etc.): n 1 2 3 4 5 1 5 8 11 12nn 6 7 8 2 6 9nn 9 10 11 3 7 10nn12 4nnMr. Young wonders how many different arrangements of the students there might be for a given arrangement of rows. He tries counting by hand starting with rows of 3, 2 and 1 and counts 16 arrangements: n123 123 124 124 125 125 126 126 134 134 135 135 136 136 145 146nn45 46 35 36 34 36 34 35 25 26 24 26 24 25 26 25nn6 5 6 5 6 4 5 4 6 5 6 4 5 4 3 3nnMr. Young sees that counting by hand is not going to be very effective for any reasonable number of students so he asks you to help out by writing a computer program to determine the number of different arrangements of students for a given set of rows.nInputnnThe input for each problem instance will consist of two lines. The first line gives the number of rows, k, as a decimal integer. The second line contains the lengths of the rows from back to front (n1, n2,..., nk) as decimal integers separated by a single space. The problem set ends with a line with a row count of 0. There will never be more than 5 rows and the total number of students, N, (sum of the row lengths) will be at most 30.nOutputnnThe output for each problem instance shall be the number of arrangements of the N students into the given rows so that the heights decrease along each row from left to right and along each column from back to front as a decimal integer. (Assume all heights are distinct.) The result of each problem instance should be on a separate line. The input data will be chosen so that the result will always fit in an unsigned 32 bit integer.nSample Inputnn1n30n5n1 1 1 1 1n3n3 2 1n4n5 3 3 1n5n6 5 4 3 2n2n15 15n0nSample Outputnn1n1n16n4158n141892608n9694845

没有更多推荐了,返回首页