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;
}