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 = 0, f = 1; char ch = getchar();while(ch < '0' || ch > '9') {if(ch == '-')f = -1;ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * f;
}
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 5;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;int main() {
#ifndef ONLINE_JUDGEFIN
#endifint n, k;cin >> n >> k;int g = __gcd(n, k);LL ans = 1LL * k * g * (n / g - 1) + 1LL * (g - 1) * (k - 1);cout << ans << endl;return 0;
}

View Code

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 = 0, f = 1; char ch = getchar();while(ch < '0' || ch > '9') {if(ch == '-')f = -1;ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * f;
}
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 5;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;int  n;
char s[maxn];int main() {
#ifndef ONLINE_JUDGEFIN
#endifscanf("%d", &n);scanf("%s", s + 1);for(int i = 1; i <= n; i++) {s[i + n] = s[i];}bool flag = 0;for(int i = 1; i <= n; i++) {if(s[i] < s[0]) {flag = 1;break;}}if(flag) {cout << "NO" << endl;} else {int i = 1, j = 2, k;while(i <= n && j <= n) {for(k = 0; k <= n && s[i + k] == s[j + k]; k++);if(k == n) break;if(s[i + k] > s[j + k]) {i = i + k + 1;if(i == j)i++;} else {j = j + k + 1;if(i == j) j++;}}int ans = min(i, j);if(ans != 1) cout << "NO" << endl;else cout << "YES" << endl;}return 0;
}

View Code

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 = 0, f = 1; char ch = getchar();while(ch < '0' || ch > '9') {if(ch == '-')f = -1;ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * f;
}
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 2e6 + 5;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
int v[maxn], prime[maxn];
int m;
void xprime(int n) {memset(v, 0, sizeof(v));m = 0;for(int i = 2; i <= n; i++) {if(v[i] == 0) {v[i] = i;prime[m++] = i;}for(int j = 1; 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 = 0; i < m && prime[i]*prime[i] <= x; i++) {if(x % prime[i] == 0) {int cnt = 0;while(x % prime[i] == 0) {//cout << prime[i] << endl;x /= prime[i];cnt++;}mp[prime[i]] += cnt; //prime的cnt次方
        }}if(x > 1) mp[x]++;//cout << x << endl;
}
vector<int> vec;//vec[i]存的是每一个素数的幂次项是多少
bool vis[3005][1005];
LL dp[3005][1005];
//dp[i][j]指的是从大数的第一个i素因子获得带有j个除数的方案数
//设当前的幂为b时,除数的数量=b/(x+1);

LL solve(int pos, int need) {if(pos == vec.size()) {return need == 1;}if(vis[pos][need]) {return dp[pos][need];}//printf("%d %d\n", pos, need);vis[pos][need] = 1;for(int i = 0; i <= vec[pos]; i++) {//枚举幂次if(need % (i + 1) == 0) {//dp[pos][need]=dp[pos][need]+dp[pos+1][need/(i+1)];dp[pos][need] = (dp[pos][need] + solve(pos + 1, need / (i + 1))) % mod;}}return dp[pos][need];
}
int main() {
#ifndef ONLINE_JUDGEFIN
#endifxprime(1000005);int n, m;scanf("%d%d", &n, &m);for(int i = 0; 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(0, n) << endl;return 0;
}

View Code

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 = 0, f = 1; char ch = getchar();while(ch < '0' || ch > '9') {if(ch == '-')f = -1;ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * f;
}
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 5;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;int main() {
#ifndef ONLINE_JUDGEFIN
#endifLL 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) / 2 + 1;if(len > n) ans = 0;else if(rs == rt && cs == ct) {ans = n / 2;}cout << ans << endl;return 0;
}

View Code

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 = 0, f = 1; char ch = getchar();while(ch < '0' || ch > '9') {if(ch == '-')f = -1;ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * f;
}
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 5;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
int n, m;
int vis[505][505];//标记 在第i个位置 删去了j个后 所需要消耗的体力值
char str[maxn];
int dfs(int pos, int cnt) {if(cnt < 0 ) return INF;if(pos == n) return 0;// debug1(vis[pos][cnt]);if(~vis[pos][cnt]) return vis[pos][cnt];if(str[pos] == '0') return dfs(pos + 1, cnt);vis[pos][cnt] = INF;int i;for(i = pos; i < n && str[i] == '1'; ++i) {vis[pos][cnt] = min(vis[pos][cnt], dfs(i + 1, cnt - 1) + (i - pos) * (i - pos + 1) / 2);if(vis[pos][cnt] == 0) return 0;}vis[pos][cnt]  = min(vis[pos][cnt], dfs(i, cnt) + (i - pos) * (i - pos + 1) / 2);return vis[pos][cnt];
}
int main() {
#ifndef ONLINE_JUDGEFIN
#endifmemset(vis, -1, sizeof(vis));scanf("%d%d%s", &n, &m, str);for(int i = 0; i <= n; i++) {if(dfs(0, i) <= m) {printf("%d\n", i);break;}}return 0;
}

View Code

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 = 0, f = 1; char ch = getchar();while(ch < '0' || ch > '9') {if(ch == '-')f = -1;ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * f;
}
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 5;
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_JUDGEFIN
#endifint n;scanf("%d", &n);int cnt1 = 0, cnt2 = 0;for(int i = 1, op, cnt; i <= n; i++) {scanf("%d%d", &op, &cnt);if(op == 1) cnt1++;else cnt2++;LL x;for(int j = 0; j < cnt; j++) {scanf("%lld", &x);if(op == 1 && mp[x] != -1) {mp[x]++;} else {s.insert(x);mp[x] = -1;}}}int ans = 0;map<LL, int>::iterator it;for(it = mp.begin(); it != mp.end(); it++) {if(it->second == cnt1) {ans++;}}if(cnt1 == 0) {cout << (LL)( 1000000000000000000 - s.size() ) << endl;} else {cout << ans << endl;}
}

View Code

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 = 0, f = 1; char ch = getchar();while(ch < '0' || ch > '9') {if(ch == '-')f = -1;ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * f;
}
const double eps = 1e-8;
const int mod =  7777777;
const int maxn = 2e5 + 5;
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_JUDGEFIN
#endifint n;scanf("%d", &n);int minnv = INF;for(int i = 1; i <= n; i++) {scanf("%d%d", &a[i].pos, &a[i].v);}sort(a + 1, a + n + 1, cmp);int pos = n ;double ans = 0;for(int i = n - 1; i >= 0; 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 0;
}

View Code

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 = 0, f = 1; char ch = getchar();while(ch < '0' || ch > '9') {if(ch == '-')f = -1;ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * f;
}
const double eps = 1e-8;
const int mod =  7777777;
const int maxn = 2e2 + 5;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
char s[maxn];
int vis[maxn];
int mex[maxn];
int main() {
#ifndef ONLINE_JUDGEFIN
#endiffor(int i = 0; i <= maxn; i++) {memset(vis, 0, sizeof(vis));for(int j = 0; j < i; j++) {for(int k = 0; k < i; k++) {vis[mex[j]^mex[k]] = true;}}mex[i] = 0;while(vis[mex[i]]) mex[i]++;}int n;while(scanf("%d %s", &n, s) != EOF) {int ans = 0;for(int i = 0; i < n; i++) {if ((s[i] - '0') % 2 != 0) {ans ^= mex[n - i];}}if (ans) printf("TATA\n");else printf("TYNATI\n");}}

View Code

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 = 0, f = 1; char ch = getchar();while(ch < '0' || ch > '9') {if(ch == '-')f = -1;ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * f;
}
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 5;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
struct EDGE {int v, nxt;
} edge[maxn << 2];
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 != -1; i = edge[i].nxt) {dfs(edge[i].v);}r[u] = ++cur;
}int vis[maxn];
int main() {
#ifndef ONLINE_JUDGEFIN
#endifmemset(head, -1, sizeof(head));int n, m;scanf("%d%d", &n, &m);for(int i = 0, v; i < n; i++) {scanf("%d", &v);if(v != -1) {addd_edge(v, i);vis[i] = 1;}}for(int i = 0; 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 0;
}

View Code

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 = 0, f = 1; char ch = getchar();while(ch < '0' || ch > '9') {if(ch == '-')f = -1;ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * f;
}
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 5;
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, 0, sizeof(vis));queue<node> q;q.push(node(a, 1));int ans = 0;vis[a] = 1;while(!q.empty()) {node tmp = q.front();int u = tmp.u;q.pop();ans = tmp.cnt;for(int i = head[u]; i != -1; i = edge[i].nxt) {if(!vis[edge[i].v]) {q.push(node(edge[i].v, ans + 1));vis[edge[i].v] = 1;}}}return ans;}
int main() {
#ifndef ONLINE_JUDGEFIN
#endifmemset(head, -1, sizeof(head));tot = 0;scanf("%d%d", &n, &a);for(int i = 1, u, v; i < n; i++) {scanf("%d%d", &u, &v);add_edge(u, v);add_edge(v, u);}printf("%d\n", bfs());return 0;
}

View Code

转载于:https://www.cnblogs.com/buerdepepeqi/p/10479344.html

GYM 101875 2018 USP-ICMC相关推荐

  1. Factories Gym - 102222G(2018宁夏邀请赛暨2019银川icpc网络预选赛)

    第一场icpc网络赛,出的去年宁夏邀请赛原题.c题还没有读完就有ak的了..(滑稽) Byteland has nn cities numbered from 11 to nn, and n−1n−1 ...

  2. Resistors in Parallel(Gym - 102028E 2018 ICPC 焦作E题 大数+规律C++版)

    链接:传送门 题外话:这套题作为队内训练赛,然后找规律找炸了,后来补题,发现大家都在用java或者python写,太难了,不会啊,只会C++的萌新躲在墙角瑟瑟发抖,写下了这个C++版本的解题报告 题意 ...

  3. (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest

    layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest author: "luow ...

  4. (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题)

    layout: post title: (寒假开黑gym)2018 ACM-ICPC, Syrian Collegiate Programming Contest(爽题) author: " ...

  5. Gym 101845(2018 ACM-ICPC, Universidad Nacional de Colombia Programming Contest)

    Problem A Problem B 分析: 暴力查找,由操作111,我们可以知道原串的第一位可以匹配结果串的每一位,所以O(n)\mathcal{O}(n)O(n)枚举对齐判断就好:由操作222, ...

  6. Gym - 101972B Arabella Collegiate Programming Contest (2018) B. Updating the Tree 树DFS

    题面 题意:T组数据,每次给你1e5个点的树(1为根),每个点有一权值,询问1-n每个节点的子树中, 至少修改几个点的权值(每次都可以任意修改),才能让子树中任意2点的距离==他们权值差的绝对值 无解 ...

  7. Gym 101964 2018-2019 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2018)

    传送门 A.Numbers B.Broken Watch 先考虑最简单的情况,就是a,b,c都相等的情况,这个时候答案显然只会跟n有关系,在n个线段里面选3个的情况就是C(n,3),其中有一部分不合法 ...

  8. Continuous Intervals Gym - 102222L(2018宁夏邀请赛暨2019银川icpc网络预选赛)

    Lamis is a smart girl. She is interested in problems about sequences and their intervals. Here she s ...

  9. Gym 102028D Keiichi Tsuchiya the Drift King(2018 ICPC 焦作站 D 题) 计算几何

    去年暑假集训了两个月就去了焦作,这个题一直卡着到最后也没做出来,很遗憾的在人生中第一场 ICPC 比赛打了铁.当时也没有补题的习惯,这个题知道了大致做法后就放过了.今年准备银川赛区,翻出了往年的比赛真 ...

最新文章

  1. 高速上车辆追尾无法移动 众人齐力抬车温暖归途
  2. K项目小记 - 项目已开工整整四周!
  3. 【独家】深度学习论文阅读路线图
  4. 四川大学计算机学院夏欣,自适应窗口的图像平滑去噪.pdf
  5. Android Studio 配置
  6. sql查询时间大于某一时间_查询时间从24分钟到2秒钟:记一次神奇的SQL优化
  7. ASP.NET企业开发框架IsLine FrameWork系列之十三--框架配置信息大全(上)
  8. python 大众点评模拟登陆_python项目实战:模拟登陆163邮箱,简单到爆
  9. 开源中国大佬是怎么用Selenium做自动化web测试的
  10. Linux与云计算——第二阶段Linux服务器架设 第七章:网站WEB服务器架设—日志分析平台...
  11. android rsa最大加密明文大小_Android 登录密码信息进行RSA加密示例
  12. 【路由篇】01. 电脑远程访问小米路由器硬盘文件
  13. 【Unity3D】自学之路2.0
  14. window.print() 实现A4纸张打印及去掉页眉页脚及打印链接
  15. Bitmap的加载和Cache
  16. 底特律中国工程师协会研讨汽车技术新动向
  17. QGIS进行坐标转换
  18. 往日学习=【iptables实验part3-搭建简单蜜罐网络】
  19. 查看自己本机的ip地址、DNS服务器地址
  20. GitLab的安装及使用教程(超级详细)

热门文章

  1. 解决/usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.15' not found错误的解决
  2. JavaScript权威设计--JavaScript表达式与运算符(简要学习笔记五)
  3. centos配置mysql
  4. 文章内容分页功能实现
  5. php中未定义的变量使用技巧
  6. Apache Load Balance Using Haproxy
  7. 也谈WEB打印(四):让我们的模板支持打印,并根据内容动态的生成页面
  8. ole2高级编程技术 pdf_别不信,21天就可以学会python,《21天学通Python》pdf免费领取...
  9. 第三方 搜索 聚合 百度 php,百度小偷-搜索引擎聚合源码-寄生虫源码
  10. java如何画百分比圆环_canvas绘制旋转的圆环百分比进度条