GYM 101875 2018 USP-ICMC
3月自训 (1):10/12
A:
题意:每个人可以连边,最远连到第(i+k)%n个人,边权为这个人与另一个人连边距离,求生成一颗最大生成树的权值和是多少
题解:可以证明的是,我们每一个人都向接下来的第k个人连边,剩下的连第k-1个人,这样得到的边权和一定是最大的
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
LL read() {
int x = , f = ; char ch = getchar();
while(ch < '' || ch > '') {
if(ch == '-')f = -;
ch = getchar();
}
while(ch >= '' && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return x * f;
}
const double eps = 1e-;
const int mod = 1e9 + ;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f; int main() {
#ifndef ONLINE_JUDGE
FIN
#endif int n, k;
cin >> n >> k;
int g = __gcd(n, k); LL ans = 1LL * k * g * (n / g - ) + 1LL * (g - ) * (k - );
cout << ans << endl;
return ;
}
B:
题意:给你一串长度为n的数,这个数可以将后面的数挪到前面来,如果没有小于最开始的那个数的话就输出YES,否则输出NO
题解:如果后面有数字小于第一个数的话就肯定是NO了,这题的坑点就是如果前面很长一串都相同但是后面有一个比前面相同位置的数小的话也要输出NO,因为n是5e5,我们不可能检查每一个串,其实对于这个字符串,我们可以求出这个数的最小表示法的答案,如果这个字符串的最小表示法的第一个字符不是第一个的话就是NO了
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
LL read() {
int x = , f = ; char ch = getchar();
while(ch < '' || ch > '') {
if(ch == '-')f = -;
ch = getchar();
}
while(ch >= '' && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return x * f;
}
const double eps = 1e-;
const int mod = 1e9 + ;
const int maxn = 1e6 + ;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f; int n;
char s[maxn]; int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
scanf("%d", &n); scanf("%s", s + );
for(int i = ; i <= n; i++) {
s[i + n] = s[i];
}
bool flag = ;
for(int i = ; i <= n; i++) {
if(s[i] < s[]) {
flag = ;
break;
}
}
if(flag) {
cout << "NO" << endl;
} else {
int i = , j = , k;
while(i <= n && j <= n) {
for(k = ; k <= n && s[i + k] == s[j + k]; k++);
if(k == n) break;
if(s[i + k] > s[j + k]) {
i = i + k + ;
if(i == j)i++;
} else {
j = j + k + ;
if(i == j) j++;
}
}
int ans = min(i, j);
if(ans != ) cout << "NO" << endl;
else cout << "YES" << endl;
}
return ;
}
C:
题意:给出n个数和一个限制条件b,为你这n个数有多少个数的因子个数恰好等b
题解:数的范围是1e12,我们可以先预处理出1e6内的素数,然后将输入的每一个数唯一分解,得到一个素因子和其幂次的一个映射。
设dp状态为dp[i][j]指的是从大数的第一个i素因子获得带有j个除数的方案数
设当前的幂为b时,除数的数量=b/(x+1);
转移就是:dp[pos][need]=dp[pos][need]+dp[pos+1][need/(i+1)];
#include<bits/stdc++.h>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
LL read() {
int x = , f = ; char ch = getchar();
while(ch < '' || ch > '') {
if(ch == '-')f = -;
ch = getchar();
}
while(ch >= '' && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return x * f;
}
const double eps = 1e-;
const int mod = 1e9 + ;
const int maxn = 2e6 + ;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
int v[maxn], prime[maxn];
int m;
void xprime(int n) {
memset(v, , sizeof(v));
m = ;
for(int i = ; i <= n; i++) {
if(v[i] == ) {
v[i] = i;
prime[m++] = i;
}
for(int j = ; j <= m; j++) {
if(prime[j] > v[i] || prime[j] > n / i) break;
v[i * prime[j]] = prime[j];
}
}
}
set<int> st;
map<LL, int> mp;
void check(LL x) {
//唯一分解
for(int i = ; i < m && prime[i]*prime[i] <= x; i++) {
if(x % prime[i] == ) {
int cnt = ;
while(x % prime[i] == ) {
//cout << prime[i] << endl;
x /= prime[i];
cnt++;
}
mp[prime[i]] += cnt; //prime的cnt次方
}
}
if(x > ) mp[x]++;
//cout << x << endl;
}
vector<int> vec;//vec[i]存的是每一个素数的幂次项是多少
bool vis[][];
LL dp[][];
//dp[i][j]指的是从大数的第一个i素因子获得带有j个除数的方案数
//设当前的幂为b时,除数的数量=b/(x+1); LL solve(int pos, int need) {
if(pos == vec.size()) {
return need == ;
}
if(vis[pos][need]) {
return dp[pos][need];
}
//printf("%d %d\n", pos, need);
vis[pos][need] = ;
for(int i = ; i <= vec[pos]; i++) {
//枚举幂次
if(need % (i + ) == ) {
//dp[pos][need]=dp[pos][need]+dp[pos+1][need/(i+1)];
dp[pos][need] = (dp[pos][need] + solve(pos + , need / (i + ))) % mod;
}
}
return dp[pos][need];
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
xprime();
int n, m;
scanf("%d%d", &n, &m);
for(int i = ; i < m; i++) {
LL x;
scanf("%lld", &x);
check(x);//将x唯一分解
}
//map的键为素因子,值为个数
map<LL, int>::iterator it;
for(it = mp.begin(); it != mp.end(); it++) {
vec.push_back(it->second);
}
//从第0个位置开始
cout << solve(, n) << endl;
return ;
}
D:
题意:我们最多可以走n步,每一步可以走上下左右,问你从起点走到终点有多少种方法
题解:我们先计算出从起点到终点的距离len,如果len大于n,那么肯定是不能走的,否则的话我们走的方法数为(n-len)/2+1种方法
坑点,如果起点和终点是一样的话,我们的方法数是n/2
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
LL read() {
int x = , f = ; char ch = getchar();
while(ch < '' || ch > '') {
if(ch == '-')f = -;
ch = getchar();
}
while(ch >= '' && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return x * f;
}
const double eps = 1e-;
const int mod = 1e9 + ;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f; int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
LL rs, cs, rt, ct;
LL n;
scanf("%lld%lld%lld%lld%lld", &n, &rs, &cs, &rt, &ct);
LL len = abs(ct - cs) + abs(rt - rs);
LL ans = (n - len) / + ;
if(len > n) ans = ;
else if(rs == rt && cs == ct) {
ans = n / ;
}
cout << ans << endl;
return ;
}
E:
题意:给你一个长度为n的01串,0表示当天不需要工作,1表示当天需要工作,我初始时有体力值为k,如果连续工作时,我第一天需要耗费的体力值为1,第二天需要耗费的体力值为2,第三天许哟啊耗费的体力值为3,,,以此类推,问我们现在需要从这个01串中最少改变多少个1为0使得我们k个体力值够用
题解:记忆化搜索,我们记忆当我们从在第i个位置删去了j个工作日时所需要消耗的体力值,如果这个状态走过就不用走,那么复杂度就是O(ac)了(滑稽
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
LL read() {
int x = , f = ; char ch = getchar();
while(ch < '' || ch > '') {
if(ch == '-')f = -;
ch = getchar();
}
while(ch >= '' && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return x * f;
}
const double eps = 1e-;
const int mod = 1e9 + ;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
int n, m;
int vis[][];//标记 在第i个位置 删去了j个后 所需要消耗的体力值
char str[maxn];
int dfs(int pos, int cnt) {
if(cnt < ) return INF;
if(pos == n) return ;
// debug1(vis[pos][cnt]);
if(~vis[pos][cnt]) return vis[pos][cnt];
if(str[pos] == '') return dfs(pos + , cnt);
vis[pos][cnt] = INF;
int i;
for(i = pos; i < n && str[i] == ''; ++i) {
vis[pos][cnt] = min(vis[pos][cnt], dfs(i + , cnt - ) + (i - pos) * (i - pos + ) / );
if(vis[pos][cnt] == ) return ;
}
vis[pos][cnt] = min(vis[pos][cnt], dfs(i, cnt) + (i - pos) * (i - pos + ) / );
return vis[pos][cnt];
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
memset(vis, -, sizeof(vis));
scanf("%d%d%s", &n, &m, str);
for(int i = ; i <= n; i++) {
if(dfs(, i) <= m) {
printf("%d\n", i);
break;
}
}
return ;
}
F:
题意:有n个人,每个人如果有喜欢的数,那么他就只喜欢这些数,如果他有讨厌的数,那么他就喜欢除了这个数外的任何数,求有多少个数是这n个人都喜欢的
题解:map记录一下就行,如果没有只喜欢某一些数的人的话,我们就输出1e8-(所有人讨厌的数即可)
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
LL read() {
int x = , f = ; char ch = getchar();
while(ch < '' || ch > '') {
if(ch == '-')f = -;
ch = getchar();
}
while(ch >= '' && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return x * f;
}
const double eps = 1e-;
const int mod = 1e9 + ;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f; int dislike[maxn];
set<LL> s;
bool flag1[maxn];
bool flag2[maxn];
map<LL, int> mp;
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int n;
scanf("%d", &n);
int cnt1 = , cnt2 = ;
for(int i = , op, cnt; i <= n; i++) {
scanf("%d%d", &op, &cnt);
if(op == ) cnt1++;
else cnt2++;
LL x;
for(int j = ; j < cnt; j++) {
scanf("%lld", &x);
if(op == && mp[x] != -) {
mp[x]++;
} else {
s.insert(x);
mp[x] = -;
}
}
}
int ans = ;
map<LL, int>::iterator it;
for(it = mp.begin(); it != mp.end(); it++) {
if(it->second == cnt1) {
ans++;
}
}
if(cnt1 == ) {
cout << (LL)( - s.size() ) << endl;
} else {
cout << ans << endl;
}
}
G:
题意:在一条直线上有n辆车,每辆车都有自己的位置和速度,如果后面一辆车撞上前面一辆车时,后面一辆车的速度会变得和前面一辆车一样,问你什么时候不可能有车子相撞
题解:我们先将车按照pos的顺序从小到大排序,定义第一辆车为1,从n到1扫一遍,如果在第i个位置的车的速度小于我当前车的速度的话,我当前位置的的车的速度是一定会变成第i个位置的速度,否则的话,我当前位置的车是一定会被撞的,计算出被第i辆车撞的时间保存最大值即可
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
LL read() {
int x = , f = ; char ch = getchar();
while(ch < '' || ch > '') {
if(ch == '-')f = -;
ch = getchar();
}
while(ch >= '' && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return x * f;
}
const double eps = 1e-;
const int mod = ;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
struct node {
int pos, v;
} a[maxn];
bool cmp(node a, node b) {
return a.pos < b.pos;
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int n;
scanf("%d", &n);
int minnv = INF;
for(int i = ; i <= n; i++) {
scanf("%d%d", &a[i].pos, &a[i].v);
}
sort(a + , a + n + , cmp);
int pos = n ;
double ans = ;
for(int i = n - ; i >= ; i--) {
if(a[i].v <= a[pos].v) {
pos = i;
} else {
int len = a[pos].pos - a[i].pos;
int v = a[i].v - a[pos].v;
ans = max(ans, 1.0 * len / v);
}
}
printf("%.6lf", ans);
return ;
}
H:
题意:有一个密码箱,他有n个数字齿轮,每个齿轮是可以被转动的,有两个人玩起了这个游戏,现在有以下的游戏规则
1.每一轮游戏,这个人可以选择非0的一个齿轮将其减一,然后可以在当前选择的齿轮的右边选择0个、1个或者两个的其他齿轮将其变为任何数字
2.如果这个人无法选择齿轮时,他将输掉,另一个人会获胜
题解:博弈论
简单介绍一下:
Impartial Game 简单来说,就是一个游戏,双方可以进行同样的操作,也就是说局面的移动权利是对等的(Nim 是 Impartial Game,但像国际象棋之类的就不是,因为只能动自己的棋子),唯一不同的只有移动的先后。于是,如果用一个图来表示这个游戏,那么图的顶点就对应于一个游戏状态,图的边就对应于一个合法的移动。
假如在一个 Impartial Game 当中,终结状态只有一个,并且局面是不可重现的,那么整个游戏图就是一个 DAG(Directed Acyclic Graph, 有向无环图),这种情况下,可以将其等效成一个 Nim 游戏。
首先再回顾一下 Nim,有若干堆石子,A 和 B 交替移动,每次只能从某一堆中取出若干个石子,最后无法移动者必输。Nim 的结论是,将所有堆的石子数全部取异或,如果结果是 0,那么这个状态是先行者负,否则先行者胜。
然后,每堆石子其实是一个独立的 Nim,我们对于一些满足以上条件的 Impartial Game,就可以将其归约,等效于一个 Nim 游戏,他的胜负状态等效为一个 Nimber 数。至于怎么归约,就用到下面的 Sprague-Grundy 定理了,那么,下面直接上结论,要搞清楚原理,请读者自己看 Wikipedia。
Sprague-Grundy定理:对一个 Impartial Game 的状态,其等效游戏的 Nimber 数,就等于所有其后继状态 Nimber 数的 Mex 函数值。
Mex 函数:这个函数的接受一个自然数集 A,输出自然数集中减去 A 之后最小的那个整数。例如 Mex({0,1,3,4}) = 2, Mex({1,2,3}) = 0, Mex({}) = 0。
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
LL read() {
int x = , f = ; char ch = getchar();
while(ch < '' || ch > '') {
if(ch == '-')f = -;
ch = getchar();
}
while(ch >= '' && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return x * f;
}
const double eps = 1e-;
const int mod = ;
const int maxn = 2e2 + ;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
char s[maxn];
int vis[maxn];
int mex[maxn];
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
for(int i = ; i <= maxn; i++) {
memset(vis, , sizeof(vis));
for(int j = ; j < i; j++) {
for(int k = ; k < i; k++) {
vis[mex[j]^mex[k]] = true;
}
}
mex[i] = ;
while(vis[mex[i]]) mex[i]++;
}
int n;
while(scanf("%d %s", &n, s) != EOF) {
int ans = ;
for(int i = ; i < n; i++) {
if ((s[i] - '') % != ) {
ans ^= mex[n - i];
}
}
if (ans) printf("TATA\n");
else printf("TYNATI\n");
} }
I:
题意:有一个游戏,现在一共有n个人,给出n个关系,如果第i个人去的话,第a[i]个人也去
题解:一开始觉得无从下手,后来听了zgq大佬的讲解后恍然大悟,第i个人去第a[i]个人也去的话,这就形成了一组关系, 我们将这组关系作为一条边记录下来,那么这n组关系就会形成一个森林,将这个森林的边反向,将每一个被连了的点打上标记,那么没有边连的点就可以作为森林中每颗树的根节点,以根节点跑一遍dfs序,那么这个点能否到达就可以直接O(1)判断这个点的dfs序是否在另一个点内即可
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
LL read() {
int x = , f = ; char ch = getchar();
while(ch < '' || ch > '') {
if(ch == '-')f = -;
ch = getchar();
}
while(ch >= '' && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return x * f;
}
const double eps = 1e-;
const int mod = 1e9 + ;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
struct EDGE {
int v, nxt;
} edge[maxn << ];
int head[maxn], tot;
void addd_edge(int u, int v) {
edge[tot].v = v;
edge[tot].nxt = head[u];
head[u] = tot++;
}
int cur;
int l[maxn];
int r[maxn];
void dfs(int u) {
l[u] = ++cur;
for(int i = head[u]; i != -; i = edge[i].nxt) {
dfs(edge[i].v);
}
r[u] = ++cur;
} int vis[maxn];
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
memset(head, -, sizeof(head));
int n, m;
scanf("%d%d", &n, &m);
for(int i = , v; i < n; i++) {
scanf("%d", &v);
if(v != -) {
addd_edge(v, i);
vis[i] = ;
}
}
for(int i = ; i < n; i++) {
if(!vis[i]) dfs(i);
}
while(m--) {
int u, v;
scanf("%d%d", &v, &u);
if(l[u] <= l[v] && r[u] >= r[v]) {
cout << "Yes" << endl;
} else {
cout << "No " << endl;
}
}
return ;
}
L:
题意:有一个n个点的树,小明从起点出发,问他最多可以经过多少点,每个点不能经过两次
题解:从起点bfs一遍即可
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
LL read() {
int x = , f = ; char ch = getchar();
while(ch < '' || ch > '') {
if(ch == '-')f = -;
ch = getchar();
}
while(ch >= '' && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
return x * f;
}
const double eps = 1e-;
const int mod = 1e9 + ;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
struct EDGE {
int v, nxt;
} edge[maxn];
int head[maxn];
int tot;
void add_edge(int u, int v) {
edge[tot].v = v;
edge[tot].nxt = head[u];
head[u] = tot++;
}
struct node {
int u, cnt;
node() {};
node(int a, int b) {
u = a, cnt = b;
}
};
bool vis[maxn];
int n, a;
int bfs() {
memset(vis, , sizeof(vis));
queue<node> q;
q.push(node(a, ));
int ans = ;
vis[a] = ;
while(!q.empty()) {
node tmp = q.front();
int u = tmp.u;
q.pop();
ans = tmp.cnt;
for(int i = head[u]; i != -; i = edge[i].nxt) {
if(!vis[edge[i].v]) {
q.push(node(edge[i].v, ans + ));
vis[edge[i].v] = ;
}
}
}
return ans; }
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
memset(head, -, sizeof(head));
tot = ;
scanf("%d%d", &n, &a);
for(int i = , u, v; i < n; i++) {
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
printf("%d\n", bfs());
return ;
}
GYM 101875 2018 USP-ICMC的更多相关文章
- (寒假开黑gym)2018 USP Try-outs
layout: post title: (寒假开黑gym)2018 USP Try-outs author: "luowentaoaa" catalog: true tags: m ...
- GYM 101064 2016 USP Try-outs G. The Declaration of Independence 主席树
G. The Declaration of Independence time limit per test 1 second memory limit per test 256 megabytes ...
- 2018 USP Try-outsF - Optimizing Transportation in Portugal
题意:给你一副无向图,求使s到t删掉一条的最短路最大的长度 题解:先预处理s,t到每个点的最短路,二分答案,对于一条边,如果选中这条边,那么对于s->u+u->v+v->t或者s-& ...
- Week Three
2018.12.10 1.[BZOJ 4818][P 3702] 2.[AGC007 A] 3.[AGC007 B] 4.[AGC007 C] 5.[AGC007 D] 2018.12.11 1.[B ...
- Week Four
2018.12.18 1.[USACO Platinum C] 2.[Gym 102028H] 3.[BZOJ 2750] 4.[BZOJ 3238] 5.[BZOJ 4310] 6.[BZOJ 38 ...
- (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题)
layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题) author: " ...
- (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest
layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest author: "luow ...
- Gym 102056I - Misunderstood … Missing - [DP][The 2018 ICPC Asia-East Continent Final Problem I]
题目链接:https://codeforces.com/gym/102056/problem/I Warm sunshine, cool wind and a fine day, while the ...
- Gym 102056L - Eventual … Journey - [分类讨论][The 2018 ICPC Asia-East Continent Final Problem L]
题目链接:https://codeforces.com/gym/102056/problem/L LCR is really an incredible being. Thinking so, sit ...
随机推荐
- python常用命令—windows终端查看安装包信息
1, pip list 会将 Python 的所有安装包全部显示出来, 左边是包名, 右边是包的版本号. 2, pip show 包的名字 会将这个包的名字,版本号,包的功能说明,按装这个包的路径显示 ...
- py3.6+anaconda下安装opencv3
py3.6+anaconda下安装opencv3 首先声明-网上的方法大多数都是有毒的.也不知道给的什么鬼方法都不行. 我说下我的方法.去这个网站https://pypi.tuna.tsinghua. ...
- 操作系统及Python解释器工作原理讲解
操作系统介绍 操作系统位于计算机硬件与应用软件之间 是一个协调.管理.控制计算机硬件资源与软件资源的控制程序 操作系统功能: 控制硬件 把对硬件复杂的操作封装成优美简单的接口(文件),给用户或者应用程 ...
- LVS+Keepalive+Nginx实现负载均衡
本文参考:http://blog.csdn.net/yinwenjie/article/details/47211551 简单粗暴写一下,做备忘,刚刚搭好没做优化呢,后期补充 一.机器准备 LVS-M ...
- 自测之Lesson13:共享内存
题目:创建一个64K的共享内存. 实现代码: #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> ...
- 软件工程第四周作业-PSP
psp表格 类别 内容 开始时间 结束时间 中断时间 delta时间 学习 学习C# 10.6下午7:00 10.6下午8:00 - 60min 写代码 写主函数以及一些小的方法 10.7下午2:00 ...
- Java 动态绑定和多态
动态绑定和多态 动态绑定是指:"在执行程序期间(而非编译期间),判断引用所指对象的实际类型,调用其相应的方法." 动态绑定(多态)存在的条件 要有继承. 要有重写. 父类引用指向子 ...
- C#操作Excel执行分类多条件汇总合并
之前发了一片模拟合并,详见模拟Excel同一列相同值的单元格合并 在之前的文章中介绍了思想,其中Excel采用的二维数组模拟,今天花了点时间,学习了一下C#操作Excel,实现了类似的效果! 准备 需 ...
- Ubuntu使用时遇到的问题
启动时显示System program problem detected 解决办法: 打开命令行窗口:Ctrl+Alt+T 执行命令:sudo gedit /etc/default/apport 把e ...
- YaoLingJump开发者日志(六)
作为一只天才魔法少女狐,不会魔法怎么行?于是我给瑶玲增加了一个技能:魔法弹. 当然,能使用魔法的前提是得有个魔杖,像这样: 魔杖不仅能让瑶玲使用魔法,当瑶玲被攻击时还能提供2s的无敌状态: ...