2020.3.31考试 T3 f

(LCM) 只和每个质数的最大次数有关,所以考虑如果每个数都 (le 16) 我们就可以状压每个质数出现的次数

(f[i2][i3][i5][i7][i11][i13]) 为 这 (6) 个质数的出现次数 这个状态的方案数,转移的话每一项都取 (max) 即可。

现在每个数都 (le 200) ,然后需要用到一个套路,建议先做[NOI2015]寿司晚宴

一个数的 (> sqrt{200}) 的质因数次数最多是 (1) ,且最多有一个(> sqrt{200}) 的质因数,以下简称(> sqrt{200}) 的质因数为 (mx)

我们设 (dp[i2][i3][i5][i7][i11][i13]) 为 这 (6) 个质数的出现次数 这个状态所有集合的 (mx) 的积的和

将数按照 (> sqrt{n}) 的质因数 分类后,按照上面的题的套路,因为 (mx) 最多会算一次,所以我们用 (f) 表示先不管 (mx) 的转移,在最后再算出有贡献的一部分(容斥)后再乘上 (mx)

最后统计答案的时候直接枚举就行了,注意最后要 (-1),因为不包括空集。

代码是真的毒瘤。。。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;
int n, x;
LL ans;
const int N = 505, mod = 1e9 + 7;
int zhi[10] = {0, 2, 3, 5, 7, 11, 13}; //6
LL dp[8][5][4][3][3][3], f[8][5][4][3][3][3];
struct shu
{
	int mx, s[10];
	void Insert(int x)
	{
		for (int i = 1; i <= 6; ++i)
			if (!(x % zhi[i]))
				while (!(x % zhi[i]))++s[i], x /= zhi[i];
		mx = x;
	}
	friend bool operator <(const shu &a, const shu &b) {return a.mx > b.mx;}
} e[N];
signed main()
{
	cin >> n;
	for (int i = 1; i <= n; ++i)scanf("%d", &x), e[i].Insert(x);
	sort(e + 1, e + 1 + n); dp[0][0][0][0][0][0] = 1;
	for (int i = 1; i <= n; ++i)
	{
		if (e[i - 1].mx != e[i].mx || e[i].mx == 1)memcpy(f, dp, sizeof(dp));
		for (int i2 = 7; i2 >= 0; --i2)
			for (int i3 = 4; i3 >= 0; --i3)
				for (int i5 = 3; i5 >= 0; --i5)
					for (int i7 = 2; i7 >= 0; --i7)
						for (int i11 = 2; i11 >= 0; --i11)
							for (int i13 = 2; i13 >= 0; --i13)
								(f[max(i2, e[i].s[1])][max(i3, e[i].s[2])][max(i5, e[i].s[3])][max(i7, e[i].s[4])][max(i11, e[i].s[5])][max(i13, e[i].s[6])] += f[i2][i3][i5][i7][i11][i13]) %= mod;
		if (e[i + 1].mx != e[i].mx || e[i].mx == 1 || i == n)
			for (int i2 = 0; i2 <= 7; ++i2)
				for (int i3 = 0; i3 <= 4; ++i3)
					for (int i5 = 0; i5 <= 3; ++i5)
						for (int i7 = 0; i7 <= 2; ++i7)
							for (int i11 = 0; i11 <= 2; ++i11)
								for (int i13 = 0; i13 <= 2; ++i13)
									dp[i2][i3][i5][i7][i11][i13] += (f[i2][i3][i5][i7][i11][i13] - dp[i2][i3][i5][i7][i11][i13]) * e[i].mx % mod;
	}
	for (int i2 = 0, t2 = 1; i2 <= 7; ++i2, t2 *= 2)
		for (int i3 = 0, t3 = 1; i3 <= 4; ++i3, t3 *= 3)
			for (int i5 = 0, t5 = 1; i5 <= 3; ++i5, t5 *= 5)
				for (int i7 = 0, t7 = 1; i7 <= 2; ++i7, t7 *= 7)
					for (int i11 = 0, t11 = 1; i11 <= 2; ++i11, t11 *= 11)
						for (int i13 = 0, t13 = 1; i13 <= 2; ++i13, t13 *= 13)
							(ans += (LL)t2 * t3 % mod * t5 % mod * t7 % mod * t11 % mod * t13 % mod * dp[i2][i3][i5][i7][i11][i13]) %= mod;
	cout << ((ans - 1) % mod + mod) % mod;
	return 0;
}
原文地址:https://www.cnblogs.com/wljss/p/12643656.html