【题解】「退群杯」3rd 热身赛

关于正赛:
就做了个线段树优化建图的板子题;不会思考,不会推柿子,不会高精,不会py

A

给 n 个数,给定 n 的因数 k,询问是否任意数的出现次数都是 k 的倍数

有一个比较好想的方法:把每个数哈希成一个小于 1e6 的数,开个桶统计
另一个方法是求所有数的 k 进制的异或和(指 k 进制下每一位 相加并对 k 取模),但是需要先把每个数哈希一下,分散到整个数域里,防止k=2然后2xor3xor4xor5=0这种

D

给定正整数 n,1 到 n 的每个正整数 i 最多选 i 次,求总和等于 n 的方案数

总和等于 n,那么大于 \(\sqrt n\) 的数不超过 \(\sqrt n\) 次。嗯,不会了
首先想到分成小于 \(\sqrt n\) 和大于 \(\sqrt n\) 的数统计
对于小于 \(\sqrt n\) 的数,直接多重背包:\(f[i][j]\) 表示前 i 个数总和 j 的方案数,有一个 \(O(n^2)\) 的类似容斥的写法,见代码
对于大于 \(\sqrt n\) 的数,每个数取不满相当于完全背包,然后有一种完全背包的计算方式
考虑这么一种构造答案的方法,对于当前的一个物品集合,可以:

  1. 加入一个数 \(\sqrt n\)
  2. 所有数加 1

显然能不重不漏地得到所有可能的方案,所以设 \(f[i][j]\) 表示当前有 i 个物品,总和 j 的方案数,按上述的转移:(\(M = \sqrt n\)

\[f[i][j] = f[i-1][j-M] + f[i][j-i] \]

这是 \(O(n\sqrt n)\)
原 来 可 以 这 么 玩
这种构造合法解的方法好像并没有什么特殊条件的限制,对于待取物品种类比较多而合法解的物品数存在一个不大的上限时比较好用
总之,假设取的物品最多为 n,体积 m,则可以这么构造答案,对于当前的一个物品集合:

  1. 加入一个最小的体积
  2. 所有数加 1

然后设 \(f[i][j]\) 表示取物品数 i,体积 m 的答案,复杂度 \(O(nm)\)

#include <cmath>
#include <cstdio>
using namespace std;
typedef long long ll;
const int mod = 998244353;
const int MAXN = 500005;
int N, M; int f[2][MAXN], g[2][MAXN], h[MAXN];
int main()
{
	scanf("%d", &N); M = (int)ceil(sqrt(N)); // [1, M), [M, N]
	f[0][0] = 1;
	int o = 0;
	for (int i=1; i< M; i++) {
		o ^= 1;
		for (int j=0; j<=N; j++) {
			f[o][j] = f[o^1][j];
			if (j>=i) {
				f[o][j] = (f[o][j]+f[o][j-i]) % mod;
				if (j>=i*(i+1))
					f[o][j] = (f[o][j]-f[o^1][j-i*(i+1)]) % mod;
			}
		//	printf("f[%d][%d] = %d\n", i, j, f[o][j]);
		}
	}
	h[0] = 1, g[0][0] = 1;
	o = 0;
	for (int i=1; i<=M; i++) {
		o ^= 1, g[o][0] = 0;
		int mj = i*M;
		for (int j=mj-M; j< mj; j++) g[o][j] = 0;
		for (int j=mj; j<=N; j++) {
			g[o][j] = (g[o^1][j-M]+g[o][j-i])%mod;
		//	printf("g[%d][%d] = %lld\n", i, j, g[o][j]);
			h[j] = (h[j]+g[o][j])%mod;
		}
	}
	int ans = 0;
	o = (M-1)&1;
//	for (int i=0; i<=N; i++) printf("f[%d] = %lld\n", i, f[o][i]);
//	for (int i=0; i<=N; i++) printf("h[%d] = %lld\n", i, h[i]);
	for (int i=0; i<=N; i++) if (f[o][i]< 0) f[o][i] += mod;
	for (int i=0; i<=N; i++) ans = (ans+1ll*f[o][i]*h[N-i]%mod)%mod;
	printf("%d\n", ans);
}
posted @ 2022-02-11 22:42  zrkc  阅读(90)  评论(0编辑  收藏  举报