2026-10-01~02 hetao1733837 的刷题记录

AT_arc156_e ARC156E Non-Adjacent Matching

原题链接:ARC156E Non-Adjacent Matching

分析

这怎么刻画?


好像可以直接容斥......就是我们看有几个点连成了 i i i 和 i + 1 i+1 i+1 之间的环......这个是不是可以 DP?那,是不是做完了?

难道我想简单了?我觉得那样的错的......还是 DP。这个 n 2 n^2 n2 是显著的。怎么设状态呢?

那么,我设 d p i , j dp_{i,j} dpi,j 表示考虑了前 i i i 个位置,有 j j j 个形如 k k k 连向 k + 1 k+1 k+1 的边的方案数。

d p i , j = ∑ k = 0 i − 1 ( − 1 ) k × d p i − 1 , k dp_{i,j}=\sum\limits_{k=0}^{i-1}{(-1)^k\times dp_{i-1,k}} dpi,j=k=0∑i−1(−1)k×dpi−1,k

答案有:

a n s = ( m + 1 ) n × ∑ k = 1 i − 1 d p n , k ans=(m+1)^n\times\sum\limits_{k=1}^{i-1}{dp_{n,k}} ans=(m+1)n×k=1∑i−1dpn,k

正能对我吃啊......


😭

我居然只考虑了一个条件😭

对于和不超过 K K K,那么,我们的总方案数应该是:

∑ i = 0 K C i + n − n × m n \sum\limits_{i=0}^{K}{C_{i+n-n\times m}^{n}} i=0∑KCi+n−n×mn

我们设 d p i , j dp_{i,j} dpi,j 表示考虑了前 i i i 个点,第 i i i 个点的度数为 j j j 的时候的方案数。

这个怎么转移呢?

感觉和上面的差不多......


决定观看题解......

???

这是啥啊😭

首先,度数和必须为奇数......这是为啥啊?后面提到,如果 ∃ i \exists i ∃i,使得 2 × ( x i + x i + 1 ) > ∑ i = 1 n x i 2\times(x_i+x_{i+1})>\sum\limits_{i=1}^{n}x_i 2×(xi+xi+1)>i=1∑nxi,那么就不合法了......将这两个点若看成一个,则必有自环......哦,这个是可以理解的。

那么,求所有在 0 , m 0,m 0,m 就是 [ 0 , ∞ ) − [ m + 1 , + ∞ ) [0,\infty)-[m+1,+\infty) [0,∞)−[m+1,+∞)。

奇数就是背包。

然后,我们还需要去重,由于两块必有交,所以,枚举中点左右,并减去中点即可。

此时,我们只需要第一部分减第二部分加第三部分即可。


这是啥啊😭

正解

cpp 复制代码
#include <bits/stdc++.h>
//#define int long long
#define mod 998244353
using namespace std;
const int N = 3005, M = 10000005;
int n, m, k;
int fac[M], inv[M];
int sum[M][2], dp1[N][N << 1][2], dp2[N << 1][2];
int qpow(int a, int b){
	int res = 1;
	while (b){
		if (b & 1)
			res = 1ll * res * a % mod;
		a = 1ll * a * a % mod;
		b >>= 1;
	}
	return res;
}
int C(int n, int m){
	if (n < 0 || m < 0 || n < m)
		return 0;
	return 1ll * fac[n] * inv[n - m] % mod * inv[m] % mod; 
}
void work_bag(int p){
	for (int i = p; i < n; i++){
		int sum[] = {0, 0};
		for (int j = m * 2; j >= 0; j--){
			swap(sum[0], sum[1]);
			sum[0] = (sum[0] + dp1[i][j][0]) % mod;
			sum[1] = (sum[1] + dp1[i][j][1]) % mod;
			if (j + m < m * 2){
				sum[(m + 1) & 1] = (sum[(m + 1) & 1] - dp1[i][j + m + 1][0] + mod) % mod;
				sum[((m + 1) & 1) ^ 1] = (sum[((m + 1) & 1) ^ 1] - dp1[i][j + m + 1][1] + mod) % mod;
			}
			dp1[i + 1][j][0] = sum[0];
			dp1[i + 1][j][1] = sum[1];
		}
	}
}
int ans1, ans2, ans3;
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m >> k;
	fac[0] = 1;
	for (int i = 1; i < M; i++){
		fac[i] = 1ll * fac[i - 1] * i % mod;
	}
	inv[M - 1] = qpow(fac[M - 1], mod - 2);
	for (int i = M - 2; i >= 0; i--){
		inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
	}
	sum[0][0] = 1;
	sum[0][1] = 0;
	for (int i = 1; i <= k; i++){
    	int tmp = C(i + n - 1, n - 1);
    	sum[i][0] = (sum[i - 1][0] + (i & 1 ? 0 : tmp)) % mod;
    	sum[i][1] = (sum[i - 1][1] + (i & 1 ? tmp : 0)) % mod;
	}
	for (int i = 0, a = 1; i <= n && i * (m + 1) <= k; i++){
		ans1 = (ans1 + 1ll * a * C(n, i) * sum[k - i * (m + 1)][i * (m + 1) & 1]) % mod;
		a *= (-1);
	}
	memset(dp1, 0, sizeof(dp1));
	for (int i = 0; i <= m; i++){
		for (int j = 0; j <= m; j++){
			if (i + j <= k && i + j > 0){
				dp1[2][min(k - i - j, i + j - 1)][(i + j) & 1]++;
			} 
		}
	}
	work_bag(2);
	for (int i = 0; i <= m * 2; i++){
		ans2 = (ans2 + dp1[n][i][0]) % mod;
	}
	memset(dp1, 0, sizeof(dp1));
	for (int i = 0; i <= m; i++){
		for (int j = 0; j <= m; j++){
			int l = abs(i - j) + 1, r = min(k - i - j, m);
			if (l < 0 || l > r)
				continue;
			int mid = (abs(i - j) + 1 + k - i - j) >> 1;
			if (l <= mid){
				int L = l, R = min(mid, r);
				dp2[L - abs(i - j) - 1][(i + L + j) & 1]++;
				dp2[R - abs(i - j)][(i + (R + 1) + j) & 1]--;
			}
			if (mid < r){
				int L = max(mid + 1, l), R = r;
				dp2[k - i - R - j][(i + R + j) & 1]++;
				dp2[k - i - L - j + 1][(i + (L - 1) + j) & 1]--;
			}
		}
	}
	for (int i = 0; i <= m * 2; i++){
		dp1[3][i][0] = dp2[i][0];
		dp1[3][i][1] = dp2[i][1];
		dp2[i + 1][1] += dp2[i][0];
		dp2[i + 1][0] += dp2[i][1];
	}
	work_bag(3);
	for (int i = 0; i <= m * 2; i++){
		ans3 = (ans3 + dp1[n][i][0]) % mod;
	}
	int tmp = ((ans2 - ans3) % mod + mod) % mod;
	cout << ((ans1 - 1ll * tmp * n % mod) % mod + mod) % mod;
}

LGP17501 ICPC 2026 Wuhan I Nailoong vs. Bombloong 2

原题链接:ICPC 2026 Wuhan I Nailoong vs. Bombloong 2

分析

我只会 2 n 2n 2n 次询问😭这并没有意义......

中午睡觉之前好像觉得链能做?不过梦到的好像不是这道题。

你谷又更新了?

但是,又有一个问题就是,如何确定这个 d e g deg deg 序列。

原来初始全部为白色吗?那不是好做多了,泪目了😭

但是,我们还是只会做 n n n 次......从某些角度而言,根节点似乎不用......

我们假设收到的序列是 a a a,那么,第 i i i 个点的儿子数量就是 a i − a i − 1 + 1 a_i-a_{i-1}+1 ai−ai−1+1。

然后,确实,一些根节点是可以不算的,那么,解决了......

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 300005;
int n, m;
vector<int> e[N];
int deg[N];
int sz[N];
int a[N];
void dfs1_milk(int u, int fa){
	sz[u] = 1;
	for (auto v : e[u]){
		if (v == fa)
			continue;
		dfs1_milk(v, u);
		sz[u] += sz[v];
	}
}
vector<int> ask;
bool cmp(int u, int v){
	return sz[u] > sz[v];
}
void dfs2_milk(int u, int fa){
	sort(e[u].begin(), e[u].end(), cmp);
	ask.push_back(u);
	for (auto v : e[u]){
		if (v == fa)
			continue;
		dfs2_milk(v, u);
	}
}
void solve_milk(){
	cin >> n;
	for (int i = 1, u, v; i < n; i++){
		cin >> u >> v;
		e[u].push_back(v);
		e[v].push_back(u);
		deg[u]++;
		deg[v]++;
	}
	int mx = 0, p = -1;
	for (int u = 1; u <= n; u++){
		int cnt = 0;
		for (auto v : e[u]){
			if (deg[v] == 1)
				cnt++;
		}
		if (cnt > mx){
			mx = cnt;
			p = u;
		}
	}
	dfs1_milk(p, 0);
	dfs2_milk(p, 0);
	cout << n - 3 << '\n';
	for (int i = 0; i < n - 3; i++){
		cout << ask[i] << " ";
	}
	cout << '\n';
	return ;
}
vector<int> g[N];
int siz[N];
int pos;
bool dfs_boom(int u){
	while (siz[u] > 0){
		siz[u]--;
		if (pos == m){
			siz[u]++;
			return false;
		}
		pos++;
		g[u].push_back(pos);
		if (!dfs_boom(pos))
			return false;
	}
	return true;
}
void solve_boom(){
	cin >> n >> m;
	for (int i = 1; i <= m; i++){
		cin >> a[i];
	}
	for (int i = 1; i <= m; i++){
		if (i == 1)
			siz[i] = a[i];
		else
			siz[i] = a[i] - a[i - 1] + 1;
	}
	pos = 1;
	dfs_boom(1);
	for (int i = 1; i <= n - 3; i++){
		while (siz[i] > 0){
			siz[i]--;
			g[i].push_back(++pos);
		}
	}
	if (pos < n){
		g[pos].push_back(pos + 1);
	}
	for (int u = 1; u <= n; u++){
		for (auto v : g[u]){
			cout << u << " " << v << '\n';
		}
	}
}
int opt;
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> opt;
	if (opt == 1){
		solve_milk();
	}
	else{
		solve_boom();
	}
}

千万不要读错题!!!

相关推荐
小虎牙^O^1 小时前
模糊数学综合评价:从模糊数学到建模评价类模型
人工智能·算法
随意起个昵称1 小时前
【单调队列优化DP】U301134 绿色通道
算法·动态规划
郝学胜-神的一滴2 小时前
AI 编程智能体 03:拆解当下主流智能体能力
开发语言·c++·人工智能·python·程序人生·游戏
Nil2082 小时前
leetcode 739每日温度
算法·leetcode·职场和发展
lvwangshu2 小时前
势能分析(摊还分析)
数据结构·数学·算法
盘古开天16662 小时前
PPO算法代码实战(三):PyTorch从零实现PPO求解CartPole
人工智能·pytorch·算法
yyy(十一月限定版)2 小时前
CF2138A Cake Assignment
算法
宵时待雨3 小时前
linux笔记归纳25:多路转接epoll
linux·服务器·网络·c++
Frank_refuel3 小时前
【C++项目】手撕JRpc框架(单机怎么优化到分布式思想)
开发语言·c++