2016-2017 ACM-ICPC, Egyptian Collegiate Programming Contest (ECPC 16)
题意:
一共有G个子游戏,一个子游戏有Bi, Ni两个数字。两名玩家开始玩游戏,每名玩家从N中减去B的任意幂次的数,直到不能操作判定为输。问谁最终能赢。
题解:
GYM - 101147 A.The game of Osho
#include <bits/stdc++.h>
using namespace std;
int t;
int g;
int b, n;
int ans;
int main() {
freopen("powers.in","r",stdin);
scanf("%d", &t);
while(t--) {
ans = ;
scanf("%d", &g);
while(g--) {
scanf("%d%d", &b, &n);
if(b&) ans ^= n&;
else {
int tt = n%(b+);
if(tt==b) ans ^= ;
else ans ^= tt&;
}
}
if(ans) puts("");
else puts("");
}
}
题意:
大矩形代表市场,大矩形当中有很多小矩形样式的伞。这些小矩形都贴着大矩形的左边或者右边且互不相交。小矩形以外的地方都是阳光。求经过大矩形时在阳光下的最短时间。
题解:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int t, n, vis[];
double L, U;
double diss[];
struct rec {
double h, w, d;
int k;
}r[];
struct node {
int to;
double val;
node(int a, double b) {
to = a; val = b;
}
};
vector<node> g[];
double distance(double x1, double y1, double x2, double y2) {
return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
void add_edge(int u, int v, double val) {
g[u].push_back(node(v, val));
g[v].push_back(node(u, val));
}
void unite(int u, int v) {
double dis;
if(r[u].k==r[v].k || r[u].w+r[v].w > U)
dis = max(r[u].d-r[v].d-r[v].h, r[v].d-r[u].d-r[u].h);
else {
if(r[u].d > r[v].d+r[v].h) dis = distance(r[u].w, r[u].d, U-r[v].w, r[v].d+r[v].h);
else if(r[v].d > r[u].d+r[u].h) dis = distance(r[v].w, r[v].d, U-r[u].w, r[u].d+r[u].h);
else dis = U-r[u].w-r[v].w;
}
add_edge(u, v, dis);
}
void spfa(int s) {
queue<int> q;
q.push(s);
memset(vis, , sizeof(vis));
vis[s] = ;
while(!q.empty()) {
int v = q.front();
q.pop();
vis[v] = ;
int len = g[v].size();
for(int i = ; i < len; i++) {
if(g[v][i].val+diss[v] < diss[g[v][i].to]) {
diss[g[v][i].to] = g[v][i].val+diss[v];
if(!vis[g[v][i].to]) {
q.push(g[v][i].to);
vis[g[v][i].to] = ;
}
}
}
}
}
int main() {
freopen("street.in","r",stdin);
scanf("%d", &t);
while(t--) {
scanf("%d%lf%lf", &n, &L, &U);
for(int i = ; i <= n+; i++) {
g[i].clear();
if(i) diss[i] = 1e15;
}
for(int i = ; i <= n; i++) scanf("%lf%lf%lf%d", &r[i].h, &r[i].w, &r[i].d, &r[i].k);
for(int i = ; i <= n; i++) {
add_edge(, i, r[i].d);
add_edge(n+, i, L-r[i].d-r[i].h);
}
for(int i = ; i < n; i++)
for(int j = i+; j <= n; j++)
unite(i, j);
spfa();
printf("%.6lf\n", diss[n+]);
}
}
题意:
长和宽分别为M+N/2,N的矩形中。有很多敌人的点。有两种方法消灭敌人。
1.N个桶,第i个桶可以消灭i-1<=x<i中的敌人。2.M个摆(半圆)每个摆可以消灭距离他前面不超过1以内的敌人。第i个摆的圆心在(N/2,i-1),半径都为N/2。
问消灭所有敌人消耗的最少设备是多少。
题解:
#include <bits/stdc++.h>
using namespace std;
int t;
int p;
double n, m;
int ans;
int vp[];
int vis[];
int match[];
struct ndoe {
double x, y;
}w[];
double distance(double x1, double y1, double x2, double y2) {
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
vector<int> g[];
bool dfs(int u) {
for(int i = ; i < g[u].size(); i++) {
int v = g[u][i], w = match[v];
if(vis[v]) continue;
vis[v] = ;
if(w< || dfs(w)) {
match[v] = u;
return true;
}
}
return false;
}
int hungarian() {
int res = ;
memset(match, -, sizeof(match));
for(int u = ; u < n; u++) {
memset(vis, , sizeof(vis));
if(dfs(u)) res++;
}
return res;
}
int main() {
freopen("wall.in","r",stdin);
scanf("%d", &t);
while(t--) {
ans = ;
memset(vp, , sizeof(vp));
scanf("%lf%lf%d", &n, &m, &p);
for(int i = ; i < n+m; i++) g[i].clear();
for(int i = ; i <= p; i++) scanf("%lf%lf", &w[i].x, &w[i].y);
memset(vis, , sizeof(vis));
for(int i = ; i <= p; i++) {
if(distance(n/, , w[i].x, w[i].y)<=n/ || (w[i].y>m && distance(n/, m-, w[i].x, w[i].y)>1.0+n/)) {
vp[i] = ;
int v = (int)floor(w[i].x);
if(vis[v]) continue;
else {
vis[v] = ; ans++;
}
}
}
for(int i = ; i <= p; i++) {
if(vp[i]) continue;
int judge = (int)floor(w[i].x);
if(vis[judge]) continue;
int up = (int)floor(w[i].y);
for(int v = up; v >= ; v--) {
if(distance(n/, (double)v, w[i].x, w[i].y) > n/) {
int u = (int)floor(w[i].x);
g[u].push_back(v+n);
break;
}
}
}
ans += hungarian();
printf("%d\n", ans);
}
}
题意:
组合数签到题。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int t;
int n, m;
int c[][];
int main() {
freopen("popcorn.in","r",stdin);
c[][] = c[][] = ;
for(int i = ; i <= ; i++) {
c[i][] = ;
for(int j = ; j <= ; j++) c[i][j] = c[i-][j]+c[i-][j-];
}
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
printf("%d\n", c[n][m]);
}
}
题意:
n个点,每个点有个值d[i],表示他能跳到i-d[i]和i+d[i]但不能越界。问每个点跳到点n的最小步数。若不能,输出-1。
题解:
扫一遍,对于点i从点i-d[I]和i+d[i]向点i连单向边。最后从点n bfs一遍即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+;
int t;
int n, tmp;
int vis[maxn];
int ans[maxn];
struct node {
int id, val;
}temp;
vector<int> g[maxn];
int update(int id, int val) {
temp.id = id; temp.val = val;
}
void bfs() {
queue<node> q;
update(n, );
ans[n] = ;
q.push(temp);
while(!q.empty()) {
node u = q.front();
q.pop();
if(vis[u.id]) continue;
vis[u.id] = ;
int len = g[u.id].size();
for(int i = ; i < len; i++) {
int v = g[u.id][i];
if(ans[v]==-)
ans[v] = u.val+;
else ans[v] = min(ans[v], u.val+);
update(v, u.val+);
q.push(temp);
}
}
}
int main() {
freopen("jumping.in","r",stdin);
scanf("%d", &t);
while(t--) {
memset(vis, , sizeof(vis));
memset(ans, -, sizeof(ans));
scanf("%d", &n);
for(int i = ; i <= n; i++) g[i].clear();
for(int i = ; i <= n; i++) {
scanf("%d", &tmp);
if(i-tmp > ) g[i-tmp].push_back(i);
if(i+tmp <= n) g[i+tmp].push_back(i);
}
bfs();
for(int i = ; i <= n; i++) printf("%d\n", ans[i]);
}
}
题意:
一个n*n的棋盘,有m个主教。每个主教都有自己的权值p。给出一个值C,在棋盘中找到一个最大点集。这个点集中的点在同一条对角线上且对于点集中任意两点(i,j),i和j之间的主教数(包括i,j)不小于pi^2+pj^2+C。
题解:
GYM - 101147 F.Bishops Alliance
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, ll> P;
const int maxn = 1e5+;
int t;
int n, m;
ll c;
int u, v;
ll p;
int cnt;
int ans;
ll _sort[maxn<<];
int tree[maxn<<];
struct node {
int x;
ll val;
node(int a, ll b) {
x = a; val = b;
}
};
vector<P> bs[][maxn<<];
void update(int x, int val) {
while(x <= cnt) {
tree[x] = max(tree[x], val);
x += x&(-x);
}
}
int sum(int x) {
int res = ;
while(x > ) {
res = max(res, tree[x]);
x -= x&(-x);
}
return res;
}
int main() {
freopen("bishops.in","r",stdin);
scanf("%d", &t);
while(t--) {
ans = ;
scanf("%d%d%lld", &n, &m, &c);
for(int i = ; i < ; i++)
for(int j = ; j < *n; j++) bs[i][j].clear();
while(m--) {
scanf("%d%d%lld", &u, &v, &p);
p *= p;
bs[][u+v-].push_back(P(u, p));
bs[][u-v+n].push_back(P(u, p));
}
for(int i = ; i < ; i++)
for(int j = ; j < *n; j++) sort(bs[i][j].begin(), bs[i][j].end()); for(int i = ; i < ; i++)
for(int j = ; j < *n; j++) {
int len = bs[i][j].size();
cnt = ;
for(int k = ; k < len; k++) {
int x = bs[i][j][k].first;
ll p = bs[i][j][k].second;
_sort[cnt++] = -p-x;
_sort[cnt++] = p+c-x-;
}
sort(_sort, _sort+cnt);
cnt = unique(_sort, _sort+cnt)-_sort;
for(int k = ; k <= cnt; k++) tree[k] = ;
for(int k = ; k < len; k++) {
int x = bs[i][j][k].first;
ll p = bs[i][j][k].second;
int id = cnt-(lower_bound(_sort, _sort+cnt, p+c-x-)-_sort);
int tmp = sum(id);
ans = max(ans, tmp+);
id = cnt-(lower_bound(_sort, _sort+cnt, -p-x)-_sort);
update(id, tmp+);
}
}
printf("%d\n", ans);
}
}
G.The Galactic Olympics(第二类斯特林数)
题意:
N个游戏,K个孩纸。游戏之间,孩纸之间都互不相同。每个孩纸能玩多个游戏,每个游戏只能被一个孩纸玩且必须有人玩。求情况数。
题解:
第二类斯特林数的基础上乘个k!.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+;
int t;
int n, k;
ll s[][];
int main() {
freopen("galactic.in","r",stdin);
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &k);
if(n < k) {
puts("");
continue;
}
memset(s, , sizeof(s));
s[][] = ;
for(int i = ; i <= n; i++)
for(int j = ; j <= i; j++) s[i][j] = (s[i-][j-]+j*s[i-][j])%mod;
for(int i = k; i > ; i--) s[n][k] = (s[n][k]*i)%mod;
printf("%lld\n", s[n][k]);
}
}
题意:
一名突击队员初始位于点(10,1,1)。当他位于点(F,Y,X)时,他可以移动到(F-1,Y,X)或(F,Y+1,X)或(F,Y,X+1)但不能越界。现在N个地点有一定的人质数。求他一次能救最多多少人质。
题解:
dp水题。dp[i][j][k] += max(dp[i+1][j][k], max(dp[i][j-1][k], dp[i][j][k-1]))。
#include <bits/stdc++.h>
using namespace std;
int dp[][][];
int main() {
freopen("commandos.in","r",stdin);
int t, n, f, y, x, h;
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
memset(dp, , sizeof(dp));
while(n--) {
scanf("%d%d%d%d", &f, &y, &x, &h);
dp[f][y][x] += h;
}
for(int i = ; i >= ; i--) {
for(int j = ; j <= ; j++) {
for(int k = ; k <= ; k++) {
dp[i][j][k] += max(dp[i+][j][k], max(dp[i][j-][k], dp[i][j][k-]));
}
}
}
printf("%d\n", dp[][][]);
}
}
题意:
给出N个小圆的坐标及半径和一个大圆的半径。大圆的圆心位于x轴,问大圆最多能包含的小圆半径和最大为多少。
题解:
有点像差分的思想。预处理出每个小圆的范围[L,R]即在该范围时小圆在大圆内。然后扫到L时-r,扫到R时+r。
先-r后+r的原因是,排序的方式是如果第一关键字相等的话比较第二关键字。对于L=R的圆来说,肯定是先扫到-r,所以要负着来做。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<double, int> P;
const int maxn = 1e5+;
int t;
int n, m;
int x, y, r;
ll sum, ans;
P spot[maxn<<];
int main() {
freopen("walk.in","r",stdin);
scanf("%d", &t);
while(t--) {
sum = ; ans = ;
scanf("%d%d", &n, &m);
int cnt = ;
while(n--) {
scanf("%d%d%d", &x, &y, &r);
if(abs(y) > m-r) continue;
double tmp = sqrt(1.0*(m-r)*(m-r)-1.0*y*y);
spot[cnt++] = P(1.0*x-tmp, -r);
spot[cnt++] = P(1.0*x+tmp, r);
}
sort(spot, spot+cnt);
for(int i = ; i < cnt; i++) {
sum += spot[i].second;
if(ans < -sum) ans = -sum;
}
printf("%lld\n", ans);
}
}
题意:
给出一颗有点权和边权的树。求每一个点u的子树中有多少点v,使得点v到点u的距离小于等于点v的权值。
题解:
GYM - 101147 J.Whistle's New Car
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5+;
int t, n, u, v, tree[maxn], ans[maxn];
ll c, x[maxn];
struct node {
ll val; int nod;
};
node fa[][maxn], tmp;
vector<node> g[maxn];
void dfs(int u, int pre) {
fa[][u].nod = pre;
int len = g[u].size();
for(int i = ; i < len; i++) {
int v = g[u][i].nod;
if(v==pre) {
fa[][u].val = g[u][i].val;
continue;
}
dfs(v, u);
}
}
void dfs_double(int u, int pre) {
int len = g[u].size();
for(int i = ; i < len; i++) {
int v = g[u][i].nod;
if(v==pre) continue;
dfs_double(v, u);
}
tree[u]++;
ll tv = x[u];
for(int k = ; k >= ; k--) {
if(fa[k][u].val <= tv) {
tv -= fa[k][u].val;
u = fa[k][u].nod;
}
}
tree[u]--;
}
void solve(int u, int pre) {
int len = g[u].size();
for(int i = ; i < len; i++) {
int v = g[u][i].nod;
if(v==pre) continue;
solve(v, u);
}
for(int i = ; i < len; i++) {
int v = g[u][i].nod;
if(v==pre) continue;
ans[u] += tree[v]+ans[v];
}
}
int main() {
freopen("car.in","r",stdin);
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
memset(tree, , sizeof(tree));
memset(ans, , sizeof(ans));
for(int i = ; i <= n; i++) g[i].clear();
for(int i = ; i <= n; i++) scanf("%lld", &x[i]);
for(int i = ; i < n; i++) {
scanf("%d%d%lld", &u, &v, &tmp.val);
tmp.nod = v;
g[u].push_back(tmp);
tmp.nod = u;
g[v].push_back(tmp);
}
dfs(, );
for(int k = ; k < ; k++) {
for(int v = ; v <= n; v++) {
fa[k+][v].nod = fa[k][fa[k][v].nod].nod;
fa[k+][v].val = fa[k][v].val+fa[k][fa[k][v].nod].val;
}
}
dfs_double(, );
solve(, );
for(int i = ; i <= n; i++) {
printf("%d", ans[i]);
if(i==n) puts("");
else printf(" ");
}
}
}
题意:
一个人从城市0开始旅行。一共有N座城市,他每到一座城市都会寄一张明信片。给出从一座城市到另一座城市的概率和在每座城市寄出每张明信片的概率。给出长度为k的寄明信片的序列。问在该序列的条件下在第Z个城市寄出第Q张明信片的序列。
题解:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int t;
int n, m, k, q, z;
double p[][], c[][];
double dp[][], dpp[][];
int a[];
int main() {
freopen("trip.in","r",stdin);
scanf("%d", &t);
while(t--) {
memset(dp, , sizeof(dp));
memset(dpp, , sizeof(dpp));
scanf("%d%d%d%d%d", &n, &m, &k, &q, &z);
for(int i = ; i < n; i++)
for(int j = ; j < n; j++) scanf("%lf", &p[i][j]);
for(int i = ; i < n; i++)
for(int j = ; j < m; j++) scanf("%lf", &c[i][j]);
for(int i = ; i < k; i++) scanf("%d", &a[i]);
dp[][] = c[][a[]];
for(int i = ; i <= q; i++) {
for(int j = ; j < n; j++)
for(int k = ; k < n; k++)
dp[i][j] += dp[i-][k]*p[k][j]*c[j][a[i]];
}
dpp[q][z] = dp[q][z];
for(int i = q+; i < k; i++) {
for(int j = ; j < n; j++)
for(int k = ; k < n; k++) {
dp[i][j] += dp[i-][k]*p[k][j]*c[j][a[i]];
dpp[i][j] += dpp[i-][k]*p[k][j]*c[j][a[i]];
}
}
for(int i = ; i < n; i++) {
dp[k-][i] += dp[k-][i-];
dpp[k-][i] += dpp[k-][i-];
}
printf("%.3lf\n", dpp[k-][n-]/dp[k-][n-]);
}
}
2016-2017 ACM-ICPC, Egyptian Collegiate Programming Contest (ECPC 16)的更多相关文章
- 2016-2017 ACM-ICPC, Egyptian Collegiate Programming Contest (ECPC 16) 题解
题目链接:http://codeforces.com/gym/101147 2017/8/27日训练赛,题目情况9/11,Rank 4/79. A. The game of Osho 题意:定义一个子 ...
- ACM ICPC, JUST Collegiate Programming Contest (2018) Solution
A:Zero Array 题意:两种操作, 1 p v 将第p个位置的值改成v 2 查询最少的操作数使得所有数都变为0 操作为可以从原序列中选一个非0的数使得所有非0的数减去它,并且所有数不能 ...
- ACM ICPC, Amman Collegiate Programming Contest (2018) Solution
Solution A:Careful Thief 题意:给出n个区间,每个区间的每个位置的权值都是v,然后找长度为k的区间,使得这个区间的所有位置的权值加起来最大,输出最大权值, 所有区间不重叠 思路 ...
- ACM International Collegiate Programming Contest, Egyptian Collegiate Programming Contest (ECPC 2015)
A.Arcade Game(康拓展开) 题意: 给出一个每个数位都不同的数n,进行一场游戏.每次游戏将n个数的每个数位重组.如果重组后的数比原来的数大则继续游戏,否则算输.如果重组后的数是最大的数则算 ...
- ACM International Collegiate Programming Contest, Egyptian Collegiate Programming Contest (ECPC 2015) G. It is all about wisdom (二分,单源最短路)
题意:有\(n\)个点,\(m\)条边,只有当你的智力值大于这条边的\(w\)才能走,问在花费不超过\(k\)的情况下,从\(1\)走到\(n\)的所需的最小智力值. 题解:这题比赛为什么没想出来呢? ...
- Egyptian Collegiate Programming Contest (ECPC 2015)
题目链接:https://vjudge.net/contest/155219#overview. A题,用全排列来找出比当前这个数字字典序还大的排列有几个,然后前缀和dp即可.据说可以康拓展开来快速找 ...
- Egyptian Collegiate Programming Contest (ECPC 2015) C题 Connecting Graph
这题上次用的是线性求LCA过的,数据比较水,当时没有被T掉(不过线性的做法是在线的).现在重新的分析一下这个问题.在所有的操作都进行完毕以后,这个图形肯定会变成一棵树,而我们的要求是在这棵树上的一条链 ...
- Egyptian Collegiate Programming Contest 2017 (ACM ECPC 2017) - original tests edition
题目链接:https://codeforces.com/gym/101856 D. Dream Team 题意:n个点,让你连边成为一棵树,边权为顶点的GCD(u,v).求所有边权和的最大值. 思路: ...
- Gym100814B Gym100814F Gym100814I(异或) ACM International Collegiate Programming Contest, Egyptian Collegiate Programming Contest (2015) Arab Academy for Science and Technology
今日份的训练题解,今天写出来的题没有昨天多,可能是因为有些事吧... Gym100814B 这个题就是老师改卷子,忘带标准答案了,但是他改了一部分卷子,并且确定自己改的卷子没出错,他想从改过的卷子里把 ...
随机推荐
- ES6 extends继承及super使用读书笔记
extends 继承 extends 实现子类的继承 super() 表示父类的构造函数, 子类必须在 constructor中调用父类的方法,负责会报错. 子类的 this 是父类构造出来的, 再在 ...
- BZOJ1965: [Ahoi2005]SHUFFLE 洗牌(exgcd 找规律)
Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 989 Solved: 660[Submit][Status][Discuss] Description ...
- 爬虫学习(十五)——json解析
json与jsonpath 对象{}:jsonobject 对象:对象在js中表现为{}括起来的内容,数据结构为{key:value,key:value...}键值对的结构,在面向对象的结构中,key ...
- jquery横向手风琴效果2
<!doctype html> <html> <head> <meta charset="utf-8"> <script ty ...
- ZOJ3553 概率DP
Bloodsucker In 0th day, there are n-1 people and 1 bloodsucker. Every day, two and only two of them ...
- WPF 加载等待动画
原文:WPF 加载等待动画 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_29844879/article/details/80216587 ...
- getElementByName????????,????????,
getElementByName可以获取多个元素,获得的是一个数组, getElementById只能获取一个,是dom从上往下的第一个元素.
- 将list中的元素按照属性分类成树状的map
技术交流群: 233513714 public LinkedHashMap<String, List<TPhoneModel>> queryPhoneList(List< ...
- pdo事务
$pdo->beginTransaction() $pdo->commit() $pdo->rollback();
- mt_vqmon异常数据分析
mt_vqmon异常数据分析 1.首缓冲时间值异常(1) 分析:当第一个m3u8请求时,已经记录request时间,1423716972224, 正常情况会立即请求分片列表. 上述图表明请求了一个m3 ...