ComWin’ round 11部分题解
https://vjudge.net/contest/325913#overview
A.Threehouses
题意:一直二维平面上的$n$个点中,前$e$个点落在小岛周围,并且有$p$条边已经连接,问最少花费使得所有点都可以通过一些边到达小岛,两点之间建边的花费为两点间的欧式距离。
思路:根据$kruskal$求最小生成树的方法将前$e$个点合并起来,再将已有$p$条边的两点合并,之后做一次$kruskal$把所有点合并即可。
#include<bits/stdc++.h> using namespace std;
const int maxn = 1000 + 10; int fa[maxn];
double x[maxn], y[maxn], dist[maxn][maxn];
int tot;
struct node {
int u, v;
double val;
bool operator < (const node &rhs) const {
return val < rhs.val;
}
}edge[maxn * maxn]; int fr(int x) {
if(fa[x] == x) return x;
return fa[x] = fr(fa[x]);
}
void uni(int x, int y) {
x = fr(x), y = fr(y);
if(x != y) fa[x] = y;
}
void init(int n) {
tot = 0;
for(int i = 0; i <= n; i++) {
fa[i] = i;
}
}
double cal(int i, int j) {
double ret = sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
return ret;
}
int main() {
int n, e, p;
scanf("%d%d%d", &n, &e, &p);
init(n + 1);
for(int i = 1; i <= n; i++) {
scanf("%lf%lf", &x[i], &y[i]);
}
for(int i = 1; i <= n; i++) {
for(int j = i + 1; j <= n; j++) {
dist[i][j] = dist[j][i] = cal(i, j);
node now;
now.u = i, now.v = j, now.val = dist[i][j];
edge[tot++] = now;
}
}
sort(edge, edge + tot);
for(int i = 1; i <= e; i++) {
uni(0, i);
}
double ans = 0.0;
for(int i = 0; i < p; i++) {
int u, v;
scanf("%d%d", &u, &v);
uni(u, v);
}
for(int i = 0; i < tot; i++) {
node now = edge[i];
int fu = fr(now.u), fv = fr(now.v);
if(fu != fv) {
ans += now.val;
fa[fu] = fv;
}
}
printf("%.6f\n", ans);
return 0;
}
C.Cops ans Robbers
题意:给定图中只有字母点可以设立障碍,问让小偷所在的位置$B$无法达到边界所需设立障碍的最小花费。
思路:先说做法。考虑最小割,对每个点拆点,让$u$到$u^{'}$的流量为该点对应的值,如果该点不能设立障碍则为$inf$,然后对一个点$u$的相邻点连一条$u^{'}$到$v$流量为$inf$的边,如果越界那么就连向汇点$T$,流量依旧为$inf$。这样做使得每个格点所在的路径流向$T$的最小割只会被其上的价值最小的点所限制,由于建图时所有相邻格点都有连边,所以从源点出发时不会漏边。
#include<bits/stdc++.h> using namespace std;
typedef long long LL;
const int N = 1000 + 5;
const int inf = 0x3f3f3f3f;
const LL linf = 0x3f3f3f3f3f3f3f3f; int n, m, c, T;
LL val[26];
char mp[N][N];
struct Dinic {
static const int maxn = 1e6 + 5;
static const int maxm = 4e6 + 5; struct Edge {
int u, v, next;
LL flow, cap;
} edge[maxm]; int head[maxn], level[maxn], cur[maxn], eg; void addedge(int u, int v, LL cap) {
edge[eg] = {u, v, head[u], 0, cap}, head[u] = eg++;
edge[eg] = {v, u, head[v], 0, 0}, head[v] = eg++;
} void init() {
eg = 0;
memset(head, -1, sizeof head);
} bool makeLevel(int s, int t, int n) {
for(int i = 0; i < n; i++) level[i] = 0, cur[i] = head[i];
queue<int> q; q.push(s);
level[s] = 1;
while(!q.empty()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = edge[i].next) {
Edge &e = edge[i];
if(e.flow < e.cap && level[e.v] == 0) {
level[e.v] = level[u] + 1;
if(e.v == t) return 1;
q.push(e.v);
}
}
}
return 0;
} LL findpath(int s, int t, LL limit = linf) {
if(s == t || limit == 0) return limit;
for(int i = cur[s]; ~i; i = edge[i].next) {
cur[edge[i].u] = i;
Edge &e = edge[i], &rev = edge[i^1];
if(e.flow < e.cap && level[e.v] == level[s] + 1) {
LL flow = findpath(e.v, t, min(limit, e.cap - e.flow));
if(flow > 0) {
e.flow += flow;
rev.flow -= flow;
return flow;
}
}
}
return 0;
} LL max_flow(int s, int t, int n) {
LL res = 0;
while(makeLevel(s, t, n)) {
LL flow;
while((flow = findpath(s, t)) > 0) {
if(res >= linf) return res;
res += flow;
}
}
return res;
}
} di; int id(int r, int c) {
if(r < 1 || r > n || c < 1 || c > m) return T;
return (r - 1) * m + c;
} LL getVal(int r, int c) {
if(r < 1 || r > n || c < 1 || c > m) return linf;
if(mp[r][c] == '.' || mp[r][c] == 'B') return linf;
else return val[mp[r][c] - 'a'];
} int main() {
scanf("%d%d%d", &m, &n, &c);
for(int i = 1; i <= n; i++) scanf("%s", mp[i] + 1);
for(int i = 0; i < c; i++) scanf("%lld", &val[i]);
T = 2*n*m + 5;
di.init();
di.addedge(id(1, 1) + n*m, T, linf);
di.addedge(id(1, m) + n*m, T, linf);
di.addedge(id(n, 1) + n*m, T, linf);
di.addedge(id(n, m) + n*m, T, linf);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
di.addedge(id(i, j), id(i, j) + n*m, getVal(i, j));
if((i == 1 || i == n) && (j == 1 || j == m)) continue;
di.addedge(id(i, j) + n*m, id(i+1, j), linf);
di.addedge(id(i, j) + n*m, id(i-1, j), linf);
di.addedge(id(i, j) + n*m, id(i, j+1), linf);
di.addedge(id(i, j) + n*m, id(i, j-1), linf);
}
}
LL ans = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(mp[i][j] == 'B') {
ans = di.max_flow(id(i, j), T, T+10);
}
if(ans) break;
}
if(ans) break;
}
printf("%lld\n", ans >= linf ? -1 : ans);
return 0;
}
/*
10 10 1
..........
..........
..........
...a.a....
..a.a.a...
.a..B.a...
..aaaaa...
..........
..........
..........
1
*/
E.Coprime Integers
题意:给定$a,b,c,d$,求$\sum_{i=a}^{b}\sum_{j=c}^{d}[gcd(i,j)=1]$,$[t=1]$表示$t$等于$1$时的值为$1$,否则为$0$。
思路:容斥原理+莫比乌斯反演,考虑$solve(n,m)=\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=1]$,可以发现$ans=solve(b,d)-solve(a-1,d)-solve(c-1,b)+solve(a-1,c-1)$。接着考虑如何计算$solve(n,m)$
$\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=1]$
$=\sum_{i=1}^{n}\sum_{j=1}^{m}\sum_{t|i,t|j}u(t)$
$=\sum_{t=1}^{min(n,m)}u(t)\sum_{i=1}^{\left \lfloor \frac{n}{t} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{m}{t} \right \rfloor}1$
$=\sum_{t=1}^{min(n,m)}u(t)\left \lfloor \frac{n}{t} \right \rfloor\left \lfloor \frac{m}{t} \right \rfloor$
预处理莫比乌斯函数前缀和之后整除分块即可在$O(\sqrt n)$复杂度内求出一次$solve$。
#include<bits/stdc++.h> using namespace std;
typedef long long LL;
const int N = 1e7 + 5; int p[N / 10], cnt, mu[N];
bool tag[N]; void getPrime() {
mu[1] = 1;
for(int i = 2; i < N; i++) {
if(!tag[i]) {
mu[i] = -1;
p[cnt++] = i;
}
for(int j = 0; j < cnt && 1LL * p[j] * i < N; j++) {
tag[i * p[j]] = 1;
if(i % p[j] == 0) {
mu[i * p[j]] = 0;
break;
}
mu[i * p[j]] = -mu[i];
}
}
for(int i = 1; i < N; i++) mu[i] += mu[i - 1];
} LL solve(LL n, LL m) {
LL res = 0;
for(LL l = 1, r; l <= min(n, m); l = r + 1) {
r = min(n / (n / l), m / (m / l));
res += (mu[r] - mu[l - 1]) * (n / l) * (m / l);
}
return res;
} int main() {
getPrime();
LL a, b, c, d;
scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
printf("%lld\n", solve(b, d) - solve(a - 1, d) - solve(c - 1, b) + solve(a - 1, c - 1));
return 0;
}
H.Heir's Dilemma
题意:求$L$到$H$之间满足位数是$6$位,且没有某一位是$0$,且能被每一位的数字整除的数的个数。
思路:数据范围很小,暴力枚举每个数$check$是否可行即可。
#include <bits/stdc++.h> using namespace std; bool ck(int x) {
bool vis[10];
for(int i = 0; i < 10; i++) vis[i] = false;
int xx = x, xxx = x, xxxx = x;
while(xxx) {
if(xxx % 10 == 0) return false;
xxx /= 10;
}
while(xxxx) {
if(vis[xxxx % 10] == true) return false;
vis[xxxx % 10] = true;
xxxx /= 10;
}
while(xx) {
int now = xx % 10;
if(x % now != 0) return false;
xx /= 10;
}
return true;
} int main() {
int cnt = 0, a, b;
cin >> a >> b;
for(int i = a; i <= b; i++) cnt += (int)ck(i);
cout << cnt << endl;
}
ComWin’ round 11部分题解的更多相关文章
- Codeforces Global Round 11 个人题解(B题)
Codeforces Global Round 11 1427A. Avoiding Zero 题目链接:click here 待补 1427B. Chess Cheater 题目链接:click h ...
- BestCoder Round #11 (Div. 2) 题解
HDOJ5054 Alice and Bob Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...
- BestCoder Round #11 (Div. 2) 前三题题解
题目链接: huangjing hdu5054 Alice and Bob 思路: 就是(x,y)在两个參考系中的表示演全然一样.那么仅仅可能在这个矩形的中点.. 题目: Alice and Bob ...
- int和integer;Math.round(11.5)和Math.round(-11.5)
int是java提供的8种原始数据类型之一.Java为每个原始类型提供了封装类,Integer是java为int提供的封装类.int的默认值为0,而Integer的默认值为null,即Integer可 ...
- Math.round(11.5)等于()Math.round(-11.5)等于()
几天前去面试,这道简单的题目居然做错了,看来基础就是慢慢积累的.并不断使用和复习才会成为高手,假设基础不是那么熟练.恐怕在成为高手的路上会困难重重.所以在做项目的间歇时间.偶尔回顾一下最基础的知识.是 ...
- Math.round(11.5)等于多少? Math.round(-11.5)等于多少?
1.先说下怎么理解 round()方法可以这样理解: 将括号内的数+0.5之后,向下取值, 比如:round(3.4)就是3.4+0.5=3.9,向下取值是3,所以round(3.4)=3; roun ...
- Codeforces Round #543 Div1题解(并不全)
Codeforces Round #543 Div1题解 Codeforces A. Diana and Liana 给定一个长度为\(m\)的序列,你可以从中删去不超过\(m-n*k\)个元素,剩下 ...
- Codeforces Round #545 Div1 题解
Codeforces Round #545 Div1 题解 来写题解啦QwQ 本来想上红的,结果没做出D.... A. Skyscrapers CF1137A 题意 给定一个\(n*m\)的网格,每个 ...
- Codeforces Round #539 Div1 题解
Codeforces Round #539 Div1 题解 听说这场很适合上分QwQ 然而太晚了QaQ A. Sasha and a Bit of Relax 翻译 有一个长度为\(n\)的数组,问有 ...
- 【Java面试题】59 Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math类中提供了三个与取整有关的方法:ceil.floor.round,这些方法的作用与它们的英文名称的含义相对应,例如,ceil的英文意义是天花板,该方法就表示向上取整,Math.ceil(11. ...
随机推荐
- [机器学习] Yellowbrick使用笔记2-模型选择
在本教程中,我们将查看各种Scikit Learn模型的分数,并使用Yellowbrick的可视化诊断工具对它们进行比较,以便为我们的数据选择最佳的模型. 代码下载 文章目录 1 使用说明 1.1 模 ...
- vulnhub靶场之IA: KEYRING (1.0.1)
准备: 攻击机:虚拟机kali.本机win10. 靶机:IA: KEYRING (1.0.1),下载地址:https://download.vulnhub.com/ia/keyring-v1.01.o ...
- 【深入浅出Seata原理及实战】「入门基础专题」带你透析认识Seata分布式事务服务的原理和流程(1)
分布式事务的背景 随着业务的不断发展,单体架构已经无法满足我们的需求,分布式微服务架构逐渐成为大型互联网平台的首选,但所有使用分布式微服务架构的应用都必须面临一个十分棘手的问题,那就是"分布 ...
- iOS如何实现自动化打包
iOS如何实现自动化打包 前言 在我们的日常开发工作中,避免不了会出现这样的场景:需求迭代开发完成之后,需要提供ipa包给QA同学进行测试,一般会执行如下流程:1.执行Git Pull命令,拉最新的代 ...
- 音频音量调整中的ramp up & down
在日常生活中不管是打电话还是听音乐,都会遇到音量不合适而去调整音量的情况.如果音量调整软件处理不好,就会听到pop noise.产生pop noise的原因是音量直接从当前值骤变到目标值,而不是缓慢的 ...
- Java基础学习笔记-运算符ヽ( ̄▽ ̄)و
运算符 运算符-按功能分为7种 1.赋值运算符 广义赋值运算符 +=, -=, *=, /=, %=, &=, |= 一般形式:变量名 运算符=表达式 两侧的类型不一致会进行 自动类型转换 和 ...
- 【分析笔记】全志平台 gpio_wdt 驱动应用和 stack crash 解决
使用说明 第一次遇到看门狗芯片是通过切换电平信号来喂狗,如 SGM706 芯片,之前也比较少会用到看门狗芯片.原本打算参考 sunxi-wdt.c 的框架,利用定时器自己写一个,无意中发现内核已经有 ...
- Casbin: 连续3年参加Google Summer of Code的开源授权技术领导者
Casbin是一个开源的授权解决方案,很自豪的宣布它已经连续三年参加Google Summer of Code(GSoC)项目.Casbin是实现访问控制和授权管理的最受欢迎的开源项目之一.该项目广泛 ...
- 鸣人的影分身(等级考试4级 2021-03 T3)
题目: 此题题干又臭又长,直接看简化版. 鸣人的影分身(等级考试4级 2021-03 T3)等效于 把m个苹果分到n个盘子中,问有几种可能? dp[i][j]表示有i个盘子j个苹果时有多少种放法. 用 ...
- cannot load "mso.dll" vs2008 web开发问题
已成功解决办法: ①将VS 2008安装包WCUWebDesignerCoreWebDesignerCore.exe提取并重新安装: ②将C:Program Files/Common Files/Mi ...