[洛谷] P2476 [SCOI2008]着色方案 & P4448 [AHOI2018初中组]球球的排列

Description

Link1

Link2

Solution

P2476

注意到每个位置要填一种颜色,要求是不能有相邻的颜色。于是我们设s[i]a[i]前缀和,dp[i][j]表示用前i种颜色填了前s[i]个位置,恰有j组相邻位置同色的方案数。再枚举x,y,表示将第i+1种颜色分成x组,其中有y组插入之前相邻的同色位置中间,xy组插空放,不相邻。则dp[i][j]dp[i+1][jy+a[i+1]x]

转移系数就是把三步方案数乘起来:

  • 将第i+1种颜色分成x组:(a[i+1]1x1)
  • 其中有y组插入之前相邻的同色位置中间:(jy)
  • xy组插空放,不相邻:(s[i]+1jxy)(不能放在之前相邻的同色位置中间)

初始化dp[1][a[1]1]=1,答案为dp[n][0],时间复杂度为O(n3)

P4448

我们把每个a[i]都除以它的平方因子后,原问题等价于有多少种排列方式,使得没有相邻位置的a[i]相同。

设每个不同值的a[i]s[i]个。考虑到P2476是每个位置任意染颜色,而P4448是先给每个位置染上颜色后,再进行任意排列。这两个问题不同之处在与,前者每种颜色内部之间不能区分顺序,而后者可以。所以直接按照前者跑出dp[n][0]后,再乘上s[i]!即可。

Code(P2476)

#include <bits/stdc++.h>

using namespace std;

const int mod = 1e9 + 7;

int n, a[20], s[20], dp[20][80], c[80][80];

int read()
{
	int x = 0, fl = 1; char ch = getchar();
	while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
	return x * fl;
}

int main(){
	n = read();
	for (int i = 1; i <= n; i ++ ) a[i] = read(), s[i] = s[i - 1] + a[i];
	c[0][0] = 1; for (int i = 1; i <= 75; i ++ ) {c[i][0] = 1; for (int j = 1; j <= 75; j ++ ) c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;}
	dp[1][a[1] - 1] = 1;
	for (int i = 1; i <= n - 1; i ++ )
	{
		for (int j = 0; j <= s[i] - 1; j ++ )
		{
			if (!dp[i][j]) continue;
			for (int x = 1; x <= a[i + 1]; x ++ )
				for (int y = 0; y <= min(j, x); y ++ )
					dp[i + 1][j - y + a[i + 1] - x] = (dp[i + 1][j - y + a[i + 1] - x] + 1ll * dp[i][j] * c[j][y] % mod * c[a[i + 1] - 1][x - 1] % mod * c[s[i] + 1 - j][x - y] % mod) % mod;
		}
	}
	printf("%d\n", dp[n][0]);
	return 0;
}
posted @   andysj  阅读(79)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示