A层2

不知道拖了多久,我太菜了

A Coprime Arrays

完全没有想到会考莫反

形式化一下

\(\displaystyle f(k) = \sum_{a_1 = 1}^{k}\sum_{a_2 = 1}^{k}... [gcd == 1]\)

套路莫反得到

\(\displaystyle f(k) = \sum_{d = 1}^{k}\mu(d)\lfloor \frac{k}{d} \rfloor\)

然后发现 \(\lfloor \frac{k}{d} \rfloor != \lfloor \frac{k + 1}{d} \rfloor\) 时 $ d | (k + 1)$, 这样就能简单维护了

code
#include<bits/stdc++.h>

using namespace std;

const int maxn = 2000005;
const int mod = 1e9 + 7;
int n, k, cnt, prime[maxn], mu[maxn], po[maxn];
bool flag[maxn];
int qpow(int x, int y){
	int ans = 1;
	for(; y; y >>= 1, x = 1ll * x * x % mod)if(y & 1) ans = 1ll * ans * x % mod;
	return ans;
}
vector<int>p[maxn];
int main(){
	scanf("%d%d",&n,&k);
	mu[1] = 1;
	for(int i = 2; i <= k; ++i){
		if(!flag[i])prime[++cnt] = i, mu[i] = -1;
		for(int j = 1; j <= cnt && i * prime[j] <= k; ++j){
			flag[i * prime[j]] = 1;
			if(i % prime[j] == 0)break;
			mu[i * prime[j]] = -mu[i];
		}
	}
	for(int i = 1; i <= k; ++i)po[i] = qpow(i, n);
	for(int i = 1; i <= k; ++i)if(mu[i])
		for(int j = i; j <= k; j += i)p[j].push_back(i);
	int now = 0, ans = 0;
	for(int i = 1; i <= k; ++i){
		for(int v : p[i]){
			now = now - mu[v] * (po[(i - 1) / v] - po[i / v] + mod) % mod;
			now = (now % mod + mod) % mod;
		}
		ans = (ans + (now xor i)) % mod;
	}
	printf("%d\n",ans);
	return 0;
}

B Werewolves

分颜色处理,处理某个颜色时,该颜色结点权值为 \(1\) ,其他的为 \(-1\)

一个联通块有贡献,当且仅当其权值和大于 \(0\)

那么再回来看这个问题,就可以看做树形背包

每次合并一个子树的信息即可,注意这里需要有负的权值,所以我给数组下标都加上一个 \(base\)

code
#include<bits/stdc++.h>

using namespace std;

const int maxn = 3005;
const int mod = 998244353;
const int base = 3002;
int n, m, ans, col[maxn], val[maxn], f[maxn][maxn + maxn];
bool del[maxn];
vector<int>g[maxn];
int size[maxn], fa[maxn], tmp[maxn + maxn];
void pre(int x){
	size[x] = 1;
	for(int v : g[x]){
		if(v == fa[x])continue;
		fa[v] = x; pre(v);
		size[x] += size[v];
	}
}
void dfs(int x){
	if(val[x] == 1)f[x][base + 1] = 1;
	else f[x][base - 1] = 1;
	int ns = 1;
	for(int v : g[x]){
		if(v == fa[x])continue;
		dfs(v);
		for(int i = - min(ns, m); i <= min(ns, m); ++i)tmp[i + base] = f[x][i + base];
		for(int i = - min(ns, m); i <= min(ns, m); ++i)
			for(int j = -min(size[v], m); j <= min(size[v], m); ++j)
				if(i + j >= -m && i + j <= m)f[x][base + i + j] = (f[x][base + i + j] + 1ll * tmp[i + base] * f[v][j + base] % mod) % mod;
		ns += size[v];
	}
	for(int i = 1; i <= min(size[x], m); ++i)ans = (ans + f[x][i + base]) % mod;
}
int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; ++i)scanf("%d",&col[i]);
	for(int i = 1; i < n; ++i){
		int u, v; scanf("%d%d",&u, &v);
		g[u].push_back(v); g[v].push_back(u);
	}
	pre(1);
	for(int i = 1; i <= n; ++i){
		if(del[col[i]])continue;
		del[col[i]] = 1; m = 0;
		for(int j = 1; j <= n; ++j){
			val[j] = col[j] == col[i] ? 1 : -1;
			m += col[j] == col[i];
		}
		for(int j = 1; j <= n; ++j)
		  for(int k = -m; k <= m; ++k)
		    f[j][k + base] = 0;
		dfs(1);
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2022-09-12 21:11  Chen_jr  阅读(26)  评论(0编辑  收藏  举报