Loading

联赛模拟测试16(A&C未补)

A.阴阳

咕咕~

B.简单的序列

目前似乎有三种方法可过
一种就是\(Catalan\),想了一下午
还有两种是\(DP\)
\(Catalan\)
根据给定的\(s\)
看其中有多少个是失配的
比如\())(((\)
那么就要求左边的串中要出现\(2\)\((\)
同理看,右边要有\(3\)\()\)
然后分别对于左边和右边求括号匹配,就是求卡特兰数
然后答案是两边相乘的结果
关于会不会有重复计算的答案
因为枚举的是左边字符串的长度
就相当于枚举了s在整个串当中的不同位置
所以答案没有重复
不用考虑去重

Code
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;

inline int read(){
	int x = 0, w = 1;
	char ch = getchar();
	for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return x * w;
}

inline void write(register int x){
	if(x < 0) x = ~x + 1, putchar('-');
	if(x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

const int ss = 200010;
const int mod = 1e9 + 7;

int fac[ss], f[ss], inv[ss];
inline void pre(register int n){
	fac[1] = fac[0] = f[1] = f[0] = inv[1] = 1;
	for(register int i = 2; i <= n; i++) fac[i] = 1ll * i * fac[i - 1] % mod;
	for(register int i = 2; i <= n; i++) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
	for(register int i = 2; i <= n; i++) f[i] = 1ll * f[i - 1] * inv[i] % mod;
}

inline int C(register int n, register int m){
	if(!m || n == m) return 1;
	return 1ll * fac[n] * f[m] % mod * f[n - m] % mod;
}

char a[ss];
int stk[ss], top, l, r, maxx, len;
long long ans;
signed main(){
	freopen("bracket.in", "r", stdin);
	freopen("bracket.out", "w", stdout);
	register int n = read(), m = read();
	scanf("%s", a + 1);
	for(register int i = 1; i <= m; i++){
		if(a[i] == ')') top++, r++;
		else top--, l++;
		if(top > maxx) maxx = top;
	}
	if(n == m){
		register bool flag = 0;
		for(register int i = 1; i <= m; i++){
			if(a[i] == '(') ++top;
			else top--;
			if(top < 0) flag = 1;
		}
		if(!flag && top == 0) return puts("1"), 0;
		else return puts("0"), 0;
	}
	pre(n);
	len = n - m;
	for(register int i = 0; i <= len; i++)//p的长度
		for(register int j = (i + maxx + 1) / 2; j <= i; j++){
			register int now = l + j;
			register int cur = r + i - j;
			register int tmp = (n - i - m - now + cur) / 2;
			ans += (((C(i, j) - C(i, j + 1) + mod) % mod) * ((C(n - i - m, tmp) - C(n - i - m, tmp - 1) + mod) % mod)) % mod;
			if(ans >= mod) ans %= mod;
		}
	write(ans);
	puts("");
	return 0;
}

C.简单的期望

咕咕~

D.简单的操作

考场上推导出来出现奇环就\(-1\)但是其他的操作都不会了\(QWQ\)
正解\(dfs\)染色判断\(-1\)
\(bfs\)直接跑联通块的最短路的最大值
最后一遍直接统计每个联通块的答案即可
学习完之后一遍码过表示很开心

Code
/* cinput
4 6
1 2
2 3
1 3
3 4
2 4
1 4
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;

inline int read(){
	int x = 0, w = 1;
	char ch = getchar();
	for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return x * w;
}

inline void write(register int x){
	if(x < 0) x = ~x + 1, putchar('-');
	if(x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

const int ss = 100010;

struct node{
	int to, nxt;
}edge[ss << 1];

int head[ss], tot;
inline void add(register int u, register int v){
	edge[++tot].to = v;
	edge[tot].nxt = head[u];
	head[u] = tot;
}

int color[ss], belong[ss];
inline void dfs(register int u, register int col, register int cnt){
	color[u] = col;
	belong[u] = cnt;
	for(register int i = head[u]; i; i = edge[i].nxt){
		register int v = edge[i].to;
		if(!color[v]) dfs(v, -col, cnt);
		if(color[u] == color[v]){
			puts("-1");
			exit(0);
		}
	}
}

queue<int> q;
bool vis[ss];
int dis[ss];
inline int bfs(register int s){
	register int maxx = -1;
	memset(vis, 0, sizeof vis);
	q.push(s);
	dis[s] = 0;
	vis[s] = 1;
	while(!q.empty()){
		register int u = q.front();
		q.pop();
		maxx = max(maxx, dis[u]);
		for(register int i = head[u]; i; i = edge[i].nxt){
			register int v = edge[i].to;
			if(!vis[v]){
				vis[v] = 1;
				q.push(v);
				dis[v] = dis[u] + 1;
			}
		}
	}
	return maxx;
}

int tmp[ss], ans, tim;
signed main(){
	freopen("merge.in", "r", stdin);
	freopen("merge.out", "w", stdout);
	register int n = read(), m = read();
	while(m--){
		register int u = read(), v = read();
		add(u, v);
		add(v, u);
	}
	for(register int i = 1; i <= n; i++)
		if(!color[i]) dfs(i, 1, ++tim);
	for(register int i = 1; i <= n; i++)
		tmp[belong[i]] = max(tmp[belong[i]], bfs(i));
	for(register int i = 1; i <= tim; i++)
		ans += tmp[i];
	write(ans);
	puts("");
	return 0;
}
posted @ 2020-10-14 14:05  Gary_818  阅读(26)  评论(2编辑  收藏