首页 > 其他分享 >题解 P4448

题解 P4448

时间:2022-11-27 21:13:41浏览次数:36  
标签:int 题解 tot times del 空隙 P4448 new

如果这不是一道原题,这道题出的还不错,是个比较毒瘤的数数。由于我太菜了反正我自己没有做出来后面的 dp,zyf 巨佬教的。

不过听说合肥六中某巨佬当年也没做出来,平衡了

但问题是这道题是原题,我安徽人什么时候可以真正站起来(恼

首先我们会发现这道题很不好入手,所以我们考虑部分分,很容易发现 6-8 测试点 \(a_i\) 全是质数。在这些测试点里面,我们只需要相邻两个球颜色不同即可。

我的数学老师说过,没有无缘无故的爱与恨,也没有无缘无故的部分分。所以我们考虑把 \(a_i\) 为合数的情况转化成 \(a_i\) 的情况。

这个时候就容易想到这个:如果 \(xy\) 为完全平方数,\(yz\) 为完全平方数,那么 \(xz\) 也是完全平方数。证明显而易见。这个引理告诉我们,如果 \(a_i\times a_j\) 为完全平方数,\(a_j \times a_k\) 为完全平方数,\(a_i \times a_k\) 也是完全平方数。也就是说这种数字不能放在一起。如果是更多个数字也是同理。

也就是说我们可以用暴力预处理出来哪些数不能放在一起,放在一个集合里,每个集合里的数有专属的颜色,那么我们的问题就是和 \(a_i\) 是质数的部分分的问题等价了:我们有 \(n\) 个球球 \(k\) 种颜色,第 \(i\) 个颜色有 \(s_i\) 个球,相同颜色的球不能放在一起,求方案数。

然后就是我没做出来的 dp((*/ω\*)),说实话也不难


我们容易想到这样一个 dp,\(f_i\) 为前 \(i\) 种颜色的合法方案数。把从 \(i - 1\) 转移到 \(i\) 就是把 \(s_i\) 个球球插入到缝隙里面。

但是这样不能转移,炒个例子,\(i\) 从 \(3\) 转移到 \(4\),\(i = 3\) 可能是 1 1 2 3,\(i = 4\) 就是在里面添加一个 4 在前两个 1 里面,变成 1 4 1 2 3,这是合法的。

这也给我们启发,当我们添加球的时候,可能会抵消掉前面一些不合法的空隙(不合法的空隙就是两边颜色相同的空隙)。

因此我们可以也把不合法的空隙也加入状态中,\(f_{i, j}\) 为前 \(i\) 种颜色有 \(j\) 个不合法空隙。


然后我们就可以考虑转移了。

受到上面的启发,我们会发现加入球球的时候我们会新增一些非法空隙,也会抵消原来的一些非法空隙。

因此我们设新增了 \(new\) 个非法空隙,抵消了 \(del\) 个非法空隙。我们的转移就是从 \(f_{i - 1,j}\) 到 \(f_{i, j - del+new}\)。

容易发现“新增”和“抵消”是两个基本独立的问题,因此我们考虑对着两个问题分别计数,然后乘起来。

先考虑在 \(s_i\) 个球球里新增了 \(new\) 个非法空隙。炒个例子,\(i = 7, s_i = 7, new = 3\),则一种方案是 7|7|7 7|7 7 7| 代表非法空隙。我们不难发现这个就是把 \(s_i\) 个球球划分成 \((s_i - new)\) 个块,插班可得方案数为 \(C_{s_i - 1}^{s_i - new - 1}\)。

再考虑抵消 \(del\) 个,我们令 \(s_i\) 的前缀和数组为 \(tot_i\),即前 \(i\) 种颜色一共有多少个。首先我们要找 \(del\) 个原来就有的非法空隙占掉,方案数 \(C_{j}^{del}\)。然后还有 \((new - del)\) 个,能够插在合法的 \(tot_{i - 1} - j + 1\) 个空中(因为这里的空是开头的前面和最后的后面都能插入,所以是 \(tot_{i - 1} - j + 1\) 个空位),所以是 \(C_{new - del}^{tot_{i - 1} - j + 1}\)。

因此就有这样的转移 \(f_{i, j + new - del} += f_{i - 1, j}\times C_{s_i - 1}^{s_i - new - 1} \times C_{j}^{del}\times C_{new - del}^{tot_{i - 1} - j + 1}\)

细节略多,然后我自个打的时候反复身败名裂,感谢 zyf 巨佬的调代码的帮助 qwq

//SIXIANG
#include <iostream>
#include <cmath> 
#define MAXN 300
#define LL long long
#define QWQ cout << "QWQ" << endl;
using namespace std;
const LL Mod = 1e9 + 7;
LL c[310][310], f[310][310], frac[310];
bool judge(LL x) {
	LL l = 1, r = x, mid;
	while(l <= r) {
		mid = (l + r) >> 1;
		LL sqr = mid * mid; 
		if(sqr == x) return 1;
		if(sqr > x) r = mid - 1;
		else l = mid + 1;
	}
	return 0;
}
int a[MAXN + 10], cl[MAXN + 10], cnt = 0;
LL s[MAXN + 10], tot[MAXN + 10];
LL C(int n, int m) {
	if(n < m) return 0;
	else return c[n][m];
}
int main() {
	c[0][0] = 1, c[1][0] = c[1][1] = 1;
	frac[0] = 1;
	for(int p = 2; p <= 300; p++) {
		c[p][0] = 1;
		for(int i = 1; i <= p; i++)
			c[p][i] = (c[p - 1][i - 1] + c[p - 1][i]) % Mod;
	}
	for(int p = 1; p <= 300; p++)
		frac[p] = frac[p - 1] * p % Mod;
		
	int n; cin >> n;
	for(int p = 1; p <= n; p++)
		cin >> a[p];
	for(int p = 1; p <= n; p++) {
		for(int i = 1; i < p; i++) {
			if(judge(1ll * a[p] * a[i])) {
				if(cl[i]) cl[p] = cl[i];
				else cl[p] = cl[i] = ++cnt;
			}
		}
		if(!cl[p]) cl[p] = ++cnt;
	}
	
	for(int p = 1; p <= n; p++)
		s[cl[p]]++;
	for(int p = 1; p <= cnt; p++)
		tot[p] = tot[p - 1] + s[p];
	f[1][tot[1] - 1] = 1;
	for(int i = 2; i <= cnt; i++)
		for(int j = 0; j < tot[i - 1]; j++)
			for(int ne = 0; ne < s[i]; ne++)
				for(int de = 0; de + ne <= s[i]; de++) {
					if(j + ne - de < 0) continue;	
					f[i][j + ne - de] += f[i - 1][j] * C(s[i] - 1, s[i] - ne - 1) % Mod
									* C(j, de) % Mod * C(tot[i - 1] - j + 1, s[i] - ne - de) % Mod;
					f[i][j + ne - de] %= Mod;
				}
	for(int p = 1; p <= cnt; p++)
		f[cnt][0] = f[cnt][0] * 1ll * frac[s[p]] % Mod;
	cout << f[cnt][0] << endl;
}

标签:int,题解,tot,times,del,空隙,P4448,new
From: https://www.cnblogs.com/thirty-two/p/16908922.html

相关文章

  • AT_otemae2019_a 寝坊だ!ピ太郎! (You overslept, Pitaro) 题解
    题目大意:给出两个数 a,b 如果 a+0.5>b,输出 1,否则输出 0。a,b 均为整数。思路:这是一道模拟题,模拟即可。代码:注意:要开浮点型!#include<bits/stdc++.h>using......
  • CF1119E Pavel and Triangles 题解
    题面PavelandTriangles题面翻译给定n种木棍,第i+1种有ai​个,长度为2^i,求用这些木棍可以同时拼出多少个三角形(不可重复使用同一根)输入第一行n,第二行n个整数a0,a1,a2.........
  • P8867 [noip2022]建造军营 题解
    题意:给定一张图,选择一些点和一些边,使得割断任意没有选的边,被选中的点仍连通。对\(10^9+7\)取膜。\(n\leq5\cdot10^5\)这篇题解会略讲缩边,详讲自己推dp状态与......
  • Oracle的会话进程解锁及问题解决方法
    首先用dba权限的用户登陆数据库1、select*fromv$locked_object查出被锁定的对象,其中object_id是对象的ID,session_id是被锁定对象有sessionID;2、selectobject_name......
  • 『题解』Codeforces 1758B XOR = Average
    Description构造一个\(a\)序列,使\(a_1\oplusa_2\oplusa_3\oplus\cdots\oplusa_n=\dfrac{sum(a)}{n}\)。Solution第一眼看到这道题,我想到的是分情况讨论。......
  • 第十三届蓝桥杯省赛与国赛真题题解大汇总(十四届参赛者必备)
    文章前言  大家好,我是执梗。本文汇总了我写的第十三届蓝桥杯所有省赛真题与国赛真题,会针对每道题打出我自己的难度评星⭐️,也会给出每道题的算法标签,帮助大家更有针对性的去......
  • [报错解决](Error Creating bean with name ‘xxx‘)类问题解决思路
    遇到ErrorCreatingbeanwithname’'这类问题的解决思路错误日志关键部分:org.springframework.beans.factory.UnsatisfiedDependencyException:Errorcreatingbeanwi......
  • 题解 [ABC279F] BOX
    这种合并集合的操作使我们想到并查集,因此我们在并查集算法的基础上进行改造来解决问题。这里使用路径压缩实现的并查集。在记录并查集的父亲数组的同时,我们还需要记录两个......
  • 题解 [ABC279E] Cheating Amidakuji
    曾经总结过一类分治套路,没想到竟然派上用场了。这种每个操作依次缺席的问题可以通过分治来解决。设solve(l,r)表示缺席的操作在\([l,r]\)之间时求出它们的答案。设......
  • ES系列二之常见问题解决
    上篇ES系列一之java端API操作结束后本以为就相安无事了,但生产的问题是层出不穷的;下面我就再记录下近几周遇到的问题以及解决方案;一更新ES信息报错报错信息如下:UseElas......