ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF 1425B Blue and Red of Our Faculty!

2021-01-20 16:01:04  阅读:138  来源: 互联网

标签:Blue ch cur 1425B int rep CF ans mod


  • 给出 \(m\) 个环,它们两两之间有且仅有一个交点 \(1\),求出有多少种选择出 两条起点为 \(1\) 长度相同的路径分别记为 \(Red,Blue\),且边没有重复,并且不能够再拓展 的方案数,两种方案不同当且仅当至少对应的 \(Red,Blue\) 中至少有一个选取边的集合不同,保证环长度的总和小于 \(4000\)。

显然最后结束时两人相距不超过 \(1\),否则它们均可以再走一步。

每人走的路径集合必定有若干个完整的环,可以再接一段残缺的环。

那么考虑按照最终的位置分别统计。

在 \(1\) 处相遇,那么就是将所有环划分为两个不同集合,求每个集合的环长度之和相等。

均走进了同一个环,且相距为 \(0/1\),那么就是选出一个环分配给两人正整数长度,再将剩下的由两人分,可以不选某个环,总和相同的方案数。

只有 \(1\) 人走进环并且距离,另外一人在 \(1\) 处,相距为 \(1\),那么就是选出一个环的长度减 \(1\),剩下的由两人分完,总和相同的方案数。

都可以用类似于背包的方法搞。

#include <bits/stdc++.h>
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
#define per(i, a, b) for (int i = (a); i >= (b); i--)
#define fi first
#define se second
using namespace std;

typedef long long LL;
typedef pair <int, int> P;
const int inf = 0x3f3f3f3f, N = 2005, mod = 1e9 + 7;
template <typename T>
void rd_(T &x) {
	x = 0; int f = 1;
	char ch = getchar();
	for (; ch > '9' || ch < '0'; ch = getchar()) if (ch == '-') f = -1;
	for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x*10 + ch - '0';x *= f;
}

vector <int> h[N];
int n, m, s[N], tot, f[2][N<<2][2], cur, g[2][N<<2], ans;
bool vis[N];

void dfs_(int u) {
	vis[u] = 1, s[tot]++;
	for (int v, i = 0; i < (int) h[u].size(); i++) {
		v = h[u][i];
		if (vis[v]) continue;
		dfs_(v);
	}
}

int main() {
	rd_(n), rd_(m);
	for (int u, v, i = 1; i <= m; i++) {
		rd_(u), rd_(v);
		h[u].push_back(v), h[v].push_back(u);
	}
	vis[1] = 1;
	rep (i, 0, (int) h[1].size() - 1) {
		int u = h[1][i];
		if (!vis[u]) {
			s[++tot] = 1;
			dfs_(u);
		}
	}
	f[0][m][0] = 1;
	rep (i, 1, tot) {
		cur ^= 1;
		rep (j, 0, 2*m) {
			f[cur][j][0] = f[cur^1][j][0];
			f[cur][j][1] = f[cur^1][j][1];
			if (j >= s[i]) {
				f[cur][j][0] = (f[cur][j][0] + f[cur^1][j - s[i]][0])%mod;
				f[cur][j][1] = (f[cur][j][1] + f[cur^1][j - s[i]][1])%mod;
			}
			if (j + s[i] <= 2*m) {
				f[cur][j][0] = (f[cur][j][0] + f[cur^1][j + s[i]][0])%mod;
				f[cur][j][1] = (f[cur][j][1] + f[cur^1][j + s[i]][1])%mod;
			}
			rep (k, 1, s[i] - 1) {
				int d = 2*k - s[i];
				if (j >= d) f[cur][j][1] = (f[cur][j][1] + f[cur^1][j - d][0]*2ll)%mod;
			}
			rep (k, 1, s[i] - 2) {
				int d = 2*k - s[i] + 1;
				if (j >= d) f[cur][j][1] = (f[cur][j][1] + f[cur^1][j - d][0]*2ll)%mod;
			}
		}
	}
	ans = f[cur][m][1];
	g[cur = 0][m] = 1;
	rep (i, 1, tot) {
		cur ^= 1;
		rep (j, 0, 2*m) {
			g[cur][j] = 0;
			if (j >= s[i]) g[cur][j] = (g[cur][j] + g[cur^1][j - s[i]])%mod;
			if (j + s[i] <= 2*m) g[cur][j] = (g[cur][j] + g[cur^1][j + s[i]])%mod;
		}
	}
	ans = (ans + g[cur][m])%mod;
	memset(f, 0, sizeof(f));
	f[cur = 0][m][0] = 1;
	rep (i, 1, tot) {
		cur ^= 1;
		rep (j, 0, 2*m) {
			f[cur][j][0] = 0;
			f[cur][j][1] = 0;
			if (j >= s[i]) {
				f[cur][j][0] = (f[cur][j][0] + f[cur^1][j - s[i]][0])%mod;
				f[cur][j][1] = (f[cur][j][1] + f[cur^1][j - s[i]][1])%mod;
			}
			if (j + s[i] <= 2*m) {
				f[cur][j][0] = (f[cur][j][0] + f[cur^1][j + s[i]][0])%mod;
				f[cur][j][1] = (f[cur][j][1] + f[cur^1][j + s[i]][1])%mod;
			}
			if (j + s[i] - 1 <= 2*m)
				f[cur][j][1] = (f[cur][j][1] + f[cur^1][j + s[i] - 1][0]*2ll)%mod;
			if (j - (s[i] - 1) >= 0)
				f[cur][j][1] = (f[cur][j][1] + f[cur^1][j - s[i] + 1][0]*2ll)%mod;
		}
	}
	ans = (ans + f[cur][m][1])%mod;
	printf("%d\n", ans);
}

标签:Blue,ch,cur,1425B,int,rep,CF,ans,mod
来源: https://www.cnblogs.com/ympc2005/p/14303368.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有