社区讨论

40pts玄关求条(新思路)

P2467[SDOI2010] 地精部落参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mkjio43x
此快照首次捕获于
2026/01/18 17:11
上个月
此快照最后确认于
2026/01/18 17:13
上个月
查看原帖
CPP
#include<iostream>
using std::cin;
using std::cout;
int c[4300][4300];
long long n, p, f[4300][4]; //f[0] 左右山谷 [1] 左右山峰 [2]左山峰 [3]右山峰
signed main()
{
	cin >> n >> p;
	c[0][0] = 1;
	for (int i = 1; i < 4300; i++)
	{
		c[i][0] = 1;
		for (int j = 1; j <= i; j++)
		{
			c[i][j] = ((long long)c[i - 1][j] + c[i - 1][j - 1]) % p;
			c[i][j] %= p;
		}
	}
	f[1][0] = 1;
	for (int i = 2; i <= n; i++)
	{
		for (int j = 0; j < i; j++) //左半边有多少个
		{
			long long times = c[i - 1][j];
			for (int pp = 0; pp < 4; pp++)
			{
				switch (pp)
				{
					case 0:
						if (i % 2 == 0)
							break;
						if (j == 0 || j == i - 1)
							break;
						f[i][pp] += times * f[j][0] * f[i - 1 - j][0];
						f[i][pp] %= p;
						break;
					case 1:
						if (i % 2 == 0)
							break;
						if (j == 0 || j == i - 1)
							f[i][pp] += times * (f[j][2] + f[i - 1 - j][3]);
						else
							f[i][pp] += times * f[j][2] * f[i - 1 - j][3];
						f[i][pp] %= p;
						break;
					case 2:
						if (i % 2)
							break;
						if (j == 0)
							f[i][pp] += times * f[i - 1 - j][0];
						else if (j == i - 1)
							break;
						else
							f[i][pp] += times * f[j][2] * f[i - 1 - j][0];
						f[i][pp] %= p;
						break;
					case 3:
						if (i % 2)
							break;
						if (j == 0)
							break;
						else if (j == i - 1)
							f[i][pp] += times * f[i - 1][0];
						else
							f[i][pp] += times * f[j][0] * f[i - 1 - j][3];
						f[i][pp] %= p;
						break;
				}
			}
		}
	}
	cout << (f[n][0] + f[n][1] + f[n][2] + f[n][3]) % p;
	return 0;
}
正如注释所说,状态是不同长度的序列左右两端的山峰山谷情况,转移时中间这一坨,但#1~4通过,其他WA,求问

回复

0 条回复,欢迎继续交流。

正在加载回复...