2023冲刺国赛模拟25

2023冲刺国赛模拟25

A. 简单计数

枚举选择了哪里,有转移

\[ f_{n, k} = \frac{[k > 1] + [k < n] + \sum_{i > k}f_{i - 1, k} + \sum_{i < k - 1}f_{n - i - 1, k - i - 1}}{n - 1} \]

直接做 \(n^3\), 前缀和优化 \(n^2\)

注意到 \(f_{n, 1} = \frac{\sum_{i = 1}^{n}f_{i, 1} + 1}{n - 1}\)

由于我们只关心 \(k\) 是否被染色,可以把序列分成 \([1, k]\)\([k, n]\) 两部分。

发现每种操作都唯一对应两个新序列的一种操作,那么我们要求在两个序列中被染黑的概率

就是 $1 - $ 都不染黑的概率

又有 \(f_{n, k} = f_{n, n - k + 1}\)

所以

\[ f_{n, k} = 1 - (1 - f_{k, 1})(1 - f_{n - k + 1, 1}) \]

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

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
const int mod = 1e9 + 7, maxn = 1e7 + 5;
int inv[maxn], f[maxn];
void add(int &x, int y){x += y; if(x >= mod)x -= mod;}
int calc(int n, int k){	return (1 - 1ll * (1 - f[k]) * (1 - f[n - k + 1]) % mod + mod) % mod;}
int main(){
	freopen("count.in","r",stdin);
	freopen("count.out","w",stdout);
	inv[1] = 1; for(int i = 2; i <= 1e7; ++i)inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
	f[1] = 0; f[2] = 1; int sum = 0;
	for(int i = 3; i <= 1e7; ++i){
		f[i] = 1ll * inv[i - 1] * (sum + 1) % mod;
		add(sum, f[i - 1]);
	}
	int T = read();
	for(int i = 1; i <= T; ++i){
		int n = read(), k = read();
		printf("%d\n",calc(n, k));
	}
	return 0;
}

B. 队伍分配

建二分图,与源/汇点连一条流量 \(1\) 费用 \(-w\) 的边,一条流量 \(1\),费用 \(1\) 的边,二分图上的边为流量 \(+\inf\) 费用 \(0\)

跑最小费用最大流。

由于最短路情况数很少,于是魔改费用流,每次 \(spfa\) 以后跑 \(dinic\)

详见代码。

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

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
const int maxn = 2e5 + 55, M = 500000;
const ll inf = 1e15;
int n1, n2, m;
struct MCMF{
	int s, t, head[maxn], tot = 1;
	struct edge{int to, net; ll val, cost;}e[maxn * 8];
	void add(int u, int v, int w, int c){
		e[++tot].net = head[u];
		head[u] = tot;
		e[tot].to = v;
		e[tot].val = w;
		e[tot].cost = c;
	}
	void link(int u, int v, int w, int c){add(u, v, w, c); add(v, u, 0, -c);}
	bool vis[maxn]; ll dis[maxn];
	bool spfa(){
		memset(dis, 0x3f, sizeof(dis));
		memset(vis, 0, sizeof(vis));
		queue<int> q; q.push(s); dis[s] = 0; vis[s] = 1;
		while(!q.empty()){
			int x = q.front(); q.pop(); vis[x] = false;
			for(int i = head[x]; i; i = e[i].net){
				int v = e[i].to;
				if(e[i].val && dis[v] > dis[x] + e[i].cost){
					dis[v] = dis[x] + e[i].cost;
					if(!vis[v])q.push(v), vis[v] = 1;
				}
			}
		}
		return dis[t] != dis[0];
	}
	int dep[maxn], now[maxn];
	bool bfs(){
		memset(dep, 0, sizeof(dep));
		queue<int>q; dep[s] = 1; q.push(s);
		now[s] = head[s];
		while(!q.empty()){
			int x = q.front(); q.pop();
			for(int i = head[x]; i; i = e[i].net){
				int v = e[i].to;
				if(e[i].val > 0 && dep[v] == 0 && dis[v] == dis[x] + e[i].cost){
					dep[v] = dep[x] + 1;
					now[v] = head[v];
					if(v == t)return true;
					q.push(v);
				}
			}
		}
		return false;
	}
	ll dfs(int x, ll from){
		if(x == t || from <= 0)return from;
		ll res = from; int i;
		for(i = now[x]; i; i = e[i].net){
			int v = e[i].to;
			if(e[i].val > 0 && dep[v] == dep[x] + 1 && dis[v] == dis[x] + e[i].cost){
				ll k = dfs(v, min(res, e[i].val));
				if(k <= 0)dep[v] = 0;
				e[i].val -= k;
				e[i ^ 1].val += k;
				res -= k;
				if(res <= 0)break;
			}
		}
		now[x] = i;
		return from - res;
	}
	ll flow, cost;
	void mcmf(){
		while(spfa()){
			while(bfs()){
				ll k = dfs(s, inf);
				flow += k;
				cost += k * dis[t];
			}
		}
	}
	void init(){
		s = n1 + n2 + 1; t = s + 1;
		for(int i = 1; i <= n1; ++i)link(s, i, 1, -M), link(s, i, 1, 1);
		for(int i = n1 + 1; i <= n1 + n2; ++i)link(i, t, 1, -M), link(i, t, 1, 1);
		for(int i = 1; i <= m; ++i){
			int u = read(), v = read() + n1;
			link(u, v, M, 0);
		}
		mcmf();
		int node = (cost - M + 1)/ -M;
		int ans1 = n1 + n2 - node;
		int ans3 = node - flow;
		printf("%d %d\n",ans1, ans3);
	}
}W;

int main(){
	freopen("team.in","r",stdin);
	freopen("team.out","w",stdout);
	n1 = read(), n2 = read(), m = read(); W.init();	
	return 0;
}

C. 即算积和

计算几何,狗都不写

n^2暴力
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
const double eps = 1e-8;
const int maxn = 2e5 + 55;
struct node{
	int x, y;
	void in(){x = read(), y = read();}
}d[maxn];
struct line{
	node a, b;
	void in(){a.in(), b.in();}
}tmp;
bool check(const line &p, const line &q){
	if(min(p.a.x, p.b.x) <= max(q.a.x, q.b.x) && max(p.a.x, p.b.x) >= min(q.a.x, q.b.x) && min(p.a.y, p.b.y) <= max(q.a.y, q.b.y) && max(p.a.y, p.b.y) >= min(q.a.y, q.b.y)){
		double v1 = (double)(q.a.x - p.a.x) * (p.b.y - p.a.y) - (double)(q.a.y - p.a.y) * (p.b.x - p.a.x);
		double v2 = (double)(q.b.x - p.a.x) * (p.b.y - p.a.y) - (double)(q.b.y - p.a.y) * (p.b.x - p.a.x);
		double v3 = (double)(p.a.x - q.a.x) * (q.b.y - q.a.y) - (double)(p.a.y - q.a.y) * (q.b.x - q.a.x);
		double v4 = (double)(p.b.x - q.a.x) * (q.b.y - q.a.y) - (double)(p.b.y - q.a.y) * (q.b.x - q.a.x);
		if(v1 * v2 < eps && v3 * v4 < eps)return true;
		else return false;
	}else return false;
}
int n, q;
bool solve(){
	tmp.in();
	for(int i = 1; i < n; ++i)if(check(tmp, line{d[i], d[i + 1]}))return true;
	if(check(tmp, line{d[n], d[1]}))return true;
	return false;
}
int main(){
	freopen("geometry.in","r",stdin);
	freopen("geometry.out","w",stdout);
	n = read(), q = read();
	for(int i = 1; i <= n; ++i)d[i].in();
	for(int i = 1; i <= q; ++i)if(solve())printf("YES\n"); else printf("NO\n");
	return 0;
}
posted @ 2023-06-27 17:17  Chen_jr  阅读(39)  评论(0编辑  收藏  举报