2015ACM/ICPC亚洲区沈阳站 Solution
A - Pattern String
留坑。
B - Bazinga
题意:找一个最大的i,使得前i - 1个字符串中至少不是它的子串
思路:暴力找,如果有一个串已经符合条件,就不用往上更新
#include <bits/stdc++.h>
using namespace std; #define N 510 int t, n;
int vis[N];
string s[N]; int main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
for(int cas = ; cas <= t; ++cas)
{
cin >> n;
memset(vis, , sizeof vis);
for(int i = ; i <= n; ++i) cin >> s[i];
int ans = -;
for(int i = ; i <= n; ++i)
{
for(int j = i + ; j <= n; ++j)
{
if(!vis[j])
{
int tmp = s[j].find(s[i]);
if(tmp == -)
{
vis[j] = ;
ans = max(ans, j);
}
else break;
}
}
}
cout << "Case #" << cas << ": " << ans << endl;
}
return ;
}
C - Minimum Cut-Cut
留坑。
D - Pagodas
题意:刚开始集合里有a, b 两个数,每次能从集合中选出 x + y 或者 x - y 放进集合中,并且放过的不能放,不能放的输游戏
思路:考虑$gcd(x, y), 每次产生的新数肯定是gcd(x, y)的倍数$ 所以能放的数总数只有 gcd(x, y) 的倍数的个数
#include<bits/stdc++.h> using namespace std; int gcd(int a, int b)
{
return b == ? a : gcd(b, a % b);
} int n, a, b; int main()
{
int t;
scanf("%d", &t);
for(int cas = ; cas <= t; ++cas)
{
scanf("%d %d %d", &n, &a, &b);
int g = gcd(a, b);
int tmp = n / g;
printf("Case #%d: ", cas);
puts(tmp & ? "Yuwgna" : "Iaka");
}
return ;
}
E - Efficient Tree
留坑。
F - Frogs
题意:有n只青蛙,长度为m的环,每只青蛙固定步数往前跳,跳到一个点标记一下,求最后有多少点被标记
思路:先将m分解因子,对于每一个arr[i]都和m求gcd,然后将gcd的倍数标记一次,代表需要统计一次它的倍数。最后遍历一边每个因子,求出它被多用几次或者少用几次的和即可。
#include<bits/stdc++.h> using namespace std; #define ll long long
#define N 10010 ll gcd(ll a, ll b)
{
return b == ? a : gcd(b, a % b);
} int n, m;
int vis[N], used[N];
ll arr[N];
vector<int>vec; int main()
{
int t;
scanf("%d", &t);
for(int cas = ; cas <= t; ++cas)
{
scanf("%d %d", &n, &m);
memset(vis, , sizeof vis);
memset(used, , sizeof used);
vec.clear();
for(int i = ; i * i <= m; ++i)
{
if(m % i == )
{
vec.push_back(i);
if(i * i != m) vec.push_back(m / i);
}
}
sort(vec.begin(), vec.end());
int tot = vec.size();
tot--;
for(int i = ; i <= n; ++i)
{
scanf("%lld", arr + i);
ll x = gcd(arr[i], m);
for(int j = ; j < tot; ++j)
{
if(vec[j] % x == ) vis[j] = ;
}
}
ll ans = ;
for(int i = ; i < tot; ++i)
{
if(vis[i] != used[i])
{
ll tmp = (m - ) / vec[i];
ans += tmp * (tmp + ) / * vec[i] * (vis[i] - used[i]);
for(int j = i + ; j < tot; ++j)
{
if(vec[j] % vec[i] == )
{
used[j] += vis[i] - used[i];
}
}
}
}
printf("Case #%d: %lld\n", cas, ans);
}
return ;
}
G - Game of Flying Circus
题意:翻译啊翻译
思路:分类讨论
1)在1-2相遇 即v1=v2 输出Yes
2)在2-3相遇,利用二分计算出相遇点,算一下到4的时间,判断
3)在3-4相遇,利用二分计算出相遇点,算一下到1的时间,判断
4)一定No
#include<bits/stdc++.h> using namespace std; const double eps = 1e-; double T, v1, v2; int sgn(double x)
{
if(fabs(x) < eps) return ;
else return x > ? : -;
} int main()
{
int t;
scanf("%d", &t);
for(int cas = ; cas <= t; ++cas)
{
scanf("%lf %lf %lf", &T, &v1, &v2);
printf("Case #%d: ", cas);
if(sgn(v1 - v2) == ) puts("Yes");
else if(sgn( * v1 * v1 - v2 * v2) > )//2-3
{
double l = , r = 300.0;
while(r - l > eps)
{
double mid = (l + r) / 2.0;
double dis1 = sqrt(mid * mid + 300.0 * 300.0);
double t1 = dis1 / v1;
double dis2 = mid + 300.0;
double t2 = dis2 / v2;
if(sgn(t1 - t2) > )
{
l = mid;
}
else
{
r = mid;
}
}
double x = (l + r) / 2.0;
double dis1 = x + 600.0;
double t1 = dis1 / v1;
double dis2 = 600.0 - x;
double t2 = dis2 / v2 + T;
puts(sgn(t1 - t2) <= ? "Yes" : "No");
}
else if(sgn( * v1 - v2) > )//3-4
{
double l = , r = 300.0;
while(r - l > eps)
{
double mid = (l + r) / 2.0;
double dis1 = sqrt(mid * mid + 300.0 * 300.0);
double t1 = dis1 / v1;
double dis2 = 900.0 - mid;
double t2 = dis2 / v2;
if(sgn(t1 - t2) > )
{
r = mid;
}
else
{
l = mid;
}
}
double y = (l + r) / 2.0;
double dis1 = sqrt((300.0 - y) * (300.0 - y) + 300.0 * 300.0) + 900.0;
double t1 = dis1 / v1;
double dis2 = y + 300.0;
double t2 = dis2 / v2 + T;
puts(sgn(t1 - t2) <= ? "Yes" : "No");
}
else puts("No");
}
return ;
}
H - Chessboard
留坑。
I - Triple
题意:二元组$A<a, b>$ 三元组 $B<c, d, e> A * B = {<a, c, d> | <a, b> \in A , <c, d, e> \in B and b = e}$ 求有多少集合满足TOP(C)
思路:枚举B,对于每个B,我们考虑符合条件的最高的a, 因为有多个a,那么小的a肯定不会放到集合里面,
对于最大的a,我们判断二维BIT中右下角有的最大值,是否大于它本身,不是的话它就应该放进TOP(C)
要多考虑一下当前的(c, d) 有多个点的情况
#include <bits/stdc++.h>
using namespace std; #define N 100010
#define pii pair <int, int>
#define ll long long int t, n, m;
struct A
{
int a, b;
void scan()
{
scanf("%d%d", &a, &b);
}
bool operator < (const A &r) const
{
return b == r.b ? a < r.a : b < r.b;
}
}a[N]; struct B
{
int c, d, e;
void scan()
{
scanf("%d%d%d", &c, &d, &e);
}
}b[N]; pii pos[N]; struct BIT
{
int a[][]; void Init()
{
memset(a, , sizeof a);
} void update(int x, int y, int val)
{
for (int i = x; i; i -= i & -i)
for (int j = y; j; j -= j & -j)
a[i][j] = max(a[i][j], val);
} int query(int x, int y)
{
int res = ;
for (int i = x; i < ; i += i & -i)
for (int j = y; j < ; j += j & -j)
res = max(res, a[i][j]);
return res;
}
}bit; int main()
{
scanf("%d", &t);
for (int kase = ; kase <= t; ++kase)
{
printf("Case #%d: ", kase);
scanf("%d%d", &n, &m);
for (int i = ; i <= n; ++i) a[i].scan();
for (int i = ; i <= m; ++i) b[i].scan();
sort(a + , a + + n);
memset(pos, , sizeof pos);
for (int i = n; i >= ; --i)
{
int b = a[i].b;
if (!pos[b].first)
{
pos[b].first = a[i].a, ++pos[b].second;
continue;
}
if (i != n)
{
if (b == a[i + ].b && a[i].a == pos[b].first)
++pos[b].second;
}
}
bit.Init();
for (int i = ; i <= m; ++i)
{
if (pos[b[i].e].first == ) continue;
bit.update(b[i].c, b[i].d, pos[b[i].e].first);
}
ll res = ;
for (int i = ; i <= m; ++i)
{
int x = b[i].c, y = b[i].d;
if(!pos[b[i].e].first) continue;
int Max = max(bit.query(x, y + ), bit.query(x + , y));
bool flag = true;
if (Max >= pos[b[i].e].first) flag = false;
Max = bit.query(x, y); if (Max != pos[b[i].e].first) flag = false;
if (flag) res += pos[b[i].e].second;
}
printf("%lld\n", res);
}
return ;
}
J - John's Fences
留坑。
K - Kykneion asma
留坑。
L - Number Link
留坑。
M - Meeting
题意:有多个集合,集合里两个点的距离都是$t-i$ 1 和 n 要到一个地方汇合,使得最大距离最小,求汇合点
思路:考虑暴力连边的边数最大有${\sum_{i = 1}^{i = m} S_i} ^2$ 没法解决
考虑将一个集合里所有点向另一个点连权值为$t_i$的边,再从这个点向集合里所有点连权值为0的边
再对1和n分别跑最短路,枚举中间点,更新答案
#include <bits/stdc++.h>
using namespace std; #define N 2000010
#define ll long long
#define INFLL 0x3f3f3f3f3f3f3f3f int t, n, m;
int arr[N]; struct Edge
{
int to, nx; ll w;
Edge() {}
Edge(int to, int nx, ll w) : to(to), nx(nx), w(w) {}
}edge[N << ]; int head[N], pos; void Init()
{
memset(head, -, sizeof head);
pos = ;
} void addedge(int u, int v, int w)
{
edge[++pos] = Edge(v, head[u], w); head[u] = pos;
} struct node
{
int u; ll w;
node () {}
node (int u, ll w) : u(u), w(w) {}
bool operator < (const node &r) const
{
return w > r.w;
}
}; ll dist[][N];
bool used[N]; void Dijkstra(int st, int id)
{
for (int i = ; i <= n + m; ++i) dist[id][i] = INFLL, used[i] = ;
priority_queue <node> q;
q.emplace(st, );
dist[id][st] = ;
while (!q.empty())
{
int u = q.top().u; q.pop();
if (used[u]) continue;
used[u] = ;
for (int it = head[u]; ~it; it = edge[it].nx)
{
int v = edge[it].to;
if (!used[v] && dist[id][v] > dist[id][u] + edge[it].w)
{
dist[id][v] = dist[id][u] + edge[it].w;
q.emplace(v, dist[id][v]);
}
}
}
} int main()
{
scanf("%d", &t);
for (int kase = ; kase <= t; ++kase)
{
printf("Case #%d: ", kase);
scanf("%d%d", &n, &m);
Init();
for (int i = , tot, w; i <= m; ++i)
{
scanf("%d%d", &w, &tot);
for (int j = ; j <= tot; ++j) scanf("%d", arr + j);
for (int j = ; j <= tot; ++j) addedge(arr[j], i + n, w);
for (int j = ; j <= tot; ++j) addedge(i + n, arr[j], );
}
Dijkstra(, );
Dijkstra(n, );
vector <int> v;
ll Min = INFLL;
// for (int i = 1; i <= n; ++i) cout << dist[0][i] << " " << dist[1][i] << endl;
for (int i = ; i <= n; ++i) Min = min(Min, max(dist[][i], dist[][i]));
if (Min == INFLL) puts("Evil John");
else
{
for (int i = ; i <= n; ++i) if (max(dist[][i], dist[][i]) == Min)
v.push_back(i);
printf("%lld\n", Min);
for (int i = , len = v.size(); i < len; ++i) printf("%d%c", v[i], " \n"[i == len - ]);
}
}
return ;
}
C=A∗B={⟨a,c,d⟩∣⟨a,b⟩∈A, ⟨c,d,e⟩∈B and b=e}
2015ACM/ICPC亚洲区沈阳站 Solution的更多相关文章
- 2015ACM/ICPC亚洲区沈阳站 Pagodas
Pagodas Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- 2015ACM/ICPC亚洲区沈阳站 B-Bazinga
Bazinga Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- 2015ACM/ICPC亚洲区沈阳站
5510 Bazinga 题意:给出n个字符串,求满足条件的最大下标值或层数 条件:该字符串之前存在不是 它的子串 的字符串 求解si是不是sj的子串,可以用kmp算法之类的. strstr是黑科技, ...
- hdu 5510 Bazinga (kmp+dfs剪枝) 2015ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)
废话: 这道题很是花了我一番功夫.首先,我不会kmp算法,还专门学了一下这个算法.其次,即使会用kmp,但是如果暴力枚举的话,还是毫无疑问会爆掉.因此在dfs的基础上加上两次剪枝解决了这道题. 题意: ...
- 2016ACM/ICPC亚洲区沈阳站 Solution
A - Thickest Burger 水. #include <bits/stdc++.h> using namespace std; int t; int a, b; int main ...
- 2015ACM/ICPC亚洲区沈阳站 部分题解
链接在这:http://bak.vjudge.net/contest/132442#overview. A题,给出a,b和n,初始的集合中有a和b,每次都可以从集合中选择不同的两个,相加或者相减,得到 ...
- 2015ACM/ICPC亚洲区沈阳站重现赛-HDU5512-Pagodas-gcd
n pagodas were standing erect in Hong Jue Si between the Niushou Mountain and the Yuntai Mountain, l ...
- 2015ACM/ICPC亚洲区沈阳站-重现赛 M - Meeting (特殊建边,最短路)
题意:有\(n\)个点,\(m\)个集合,集合\(E_i\)中的点都与集合中的其它点有一条边权为\(t_i\)的边,现在问第\(1\)个点和第\(n\)个点到某个点的路径最短,输出最短路径和目标点,如 ...
- 2015ACM/ICPC亚洲区沈阳站-重现赛 B - Bazinga (KMP)
题意:给你\(n\)个字符串,\(s_1,s_2,...,s_n\),对于\(i(1\le i\le n)\),找到最大的\(i\),并且满足\(s_j(1\le j<i)\)不是\(s_i\) ...
随机推荐
- 上传绕过WAF的tips大全
原始默认状态: ——WebKitFormBoundary2smpsxFB3D0KbA7D Content-Disposition: form-data; name=”filepath”; filena ...
- linux大全链接
http://man.linuxde.net/
- C语言简介(转自菜鸟教程)
C 简介 C 语言是一种通用的高级语言,最初是由丹尼斯·里奇在贝尔实验室为开发 UNIX 操作系统而设计的.C 语言最开始是于 1972 年在 DEC PDP-11 计算机上被首次实现. 在 1978 ...
- 使用Editplus和Dev C++配置C++的编译运行环 境
或许大家会有疑问,为何不直接使用VC;VS;或Dev这些IDE呢?何必舍近求远.主要是因为写程序这么多年来已经习惯了Editplus,包括他的快捷键,语法自动完成,语法提示等等,Editplus用了这 ...
- Android Intent实现页面之间跳转
什么是IntentIntent可以理解为信使(意图)由Intent来协助完成Android各个组件之间的通讯Intent实现页面逐渐的跳转1.startActivity(inetnt)2.startA ...
- PyQt4开关按钮ToggleButton
PyQt4没有开关按钮部件.但是我们可以使用在特殊状态下的QPushButton部件来创建开关按钮.而所谓的开关按钮就是一个具有按下和未按下两种状态的普通赶牛.用户可以通过单击按钮来切换其开或者关的状 ...
- img-图片二进制流 64位前端显示
碰到的场景:因为使用iframe子窗口打开,多张的二维码图片创建方法调用,导致页面打开缓慢, 所以将调取方式转换成<img src="data:image/png;base64,@it ...
- C# 判断远程文件是否存在
/// <summary> /// 判断远程文件是否存在 /// </summary> /// <param name="url">url地址& ...
- fluentValidation集成到autofac
废话不说直接上代码 // 首先实现ValidatorFactory public class DependencyResolverValidatorFactory : ValidatorFactory ...
- 使用log4net记录日志到数据库(含有自定义属性)
记录日志是管理系统中对用户行为的一种监控与审核,asp.net中记录日志的方式有很多种,这里我只介绍一下最近用到的log4net,关于他的具体介绍网上有很多,我讲一下他的用法. 第一步:在配置文件中的 ...