@Dmaxiya
2018-08-17T02:14:03.000000Z
字数 6315
阅读 1166
Codeforces
Contests 链接:Codeforces Round #482 (Div. 2)
过题数:2
排名:843/10089
用最少的线将一个圆平分成 块。
输入只包含一个整数 。
输出需要的线的数量。
| 输入 |
|---|
| 3 |
| 输出 |
| 2 |
| 输入 |
|---|
| 4 |
| 输出 |
| 5 |
如果 为奇数,就要平分成偶数块,就需要 条线,如果 为偶数,就需要平分成奇数块,每条线必须从圆心往外,需要 条线,注意 为 就不需要线。
#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <climits>#include <cstring>#include <string>#include <vector>#include <list>#include <queue>#include <stack>#include <map>#include <set>#include <functional>#include <algorithm>using namespace std;#define LL long longLL int n;int main() {#ifdef LOCALfreopen("test.txt", "r", stdin);// freopen("10.out", "w", stdout);#endif // LOCALwhile(scanf("%I64d", &n) != EOF) {if(n == 0) {printf("0\n");continue;}++n;if(n % 2 == 0) {printf("%I64d\n", n / 2);} else {printf("%I64d\n", n);}}return 0;}
、 和 三人都有一个长度相同的字符串,每个字符串都只包含小写字母和大写字母,三个人都有 次对自己的字符串进行操作的机会,每次操作可以选择一个字符并将这个字符修改成另一个字符。一个字符串的价值定义为这个字符串中所有子串出现的最大次数,他们三人经过 轮操作后,在采取最优策略下,谁的字符串价值将会最大。
第一行为一个整数 ,接下去三行为三个字符串,分别为 和 的初始字符串,字符串的长度不超过 ,字符串只包含小写字母和大写字母。
输出三人都采取最优策略下,字符串价值最大的人,如果存在两个或两个以上最大价值,输出 。
| 输入 |
|---|
3KurooShiroKatie |
| 输出 |
| Kuro |
| 提示 |
轮之后, 可以将自己的字符串修改为 ooooo,价值为 ,而另外两个人最多只能得到价值为 的字符串。 |
| 输入 |
|---|
7treasurehuntthreefriendshiCodeforces |
| 输出 |
| Shiro |
| 输入 |
|---|
1abcabccbabacababca |
| 输出 |
| Katie |
| 输入 |
|---|
15foPaErcvJmZaxowpbtmkuOlaHRE |
| 输出 |
| Draw |
| 提示 |
| 每个人都可以将自己的字符串修改成 个相同的字符,因此三人平局。 |
如果某个长度大于 的子串是字符串中出现次数最多的子串,那么这个子串中的字符一定也是出现最多的子串,因此只要处理所有字符即可,对于每个人都计算出可能的最大价值再进行比较就能知道赢家。如果某个字符串的字符完全相等且 等于 ,那么这个符串的价值只能等于 ,如果 (其中 为字符出现的最大次数),那么最大价值就是 ,否则字符串的价值就可以达到 。
#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <climits>#include <cstring>#include <string>#include <vector>#include <list>#include <queue>#include <stack>#include <map>#include <set>#include <functional>#include <algorithm>using namespace std;#define LL long longconst int maxn = 100000 + 100;int n;char str[3][maxn];int score[3];map<char, int> mp[3];int len[3];map<int, int> mpp;map<int, int>::iterator it;int getscore(int Index, char ch) {int tmp = n - (len[Index] - mp[Index][ch]);if(tmp >= 0) {if(mp[Index][ch] == len[Index] && tmp == 1) {return len[Index] - 1;}return len[Index];}return n + mp[Index][ch];}int main() {#ifdef LOCALfreopen("test.txt", "r", stdin);// freopen("10.out", "w", stdout);#endif // LOCALwhile(scanf("%d", &n) != EOF) {mpp.clear();memset(score, 0, sizeof(score));for(int i = 0; i < 3; ++i) {mp[i].clear();scanf("%s", str[i]);len[i] = strlen(str[i]);for(int j = 0; str[i][j]; ++j) {++mp[i][str[i][j]];}}for(char ch = 'a'; ch <= 'z'; ++ch) {for(int i = 0; i < 3; ++i) {score[i] = max(score[i], getscore(i, ch));}}for(char ch = 'A'; ch <= 'Z'; ++ch) {for(int i = 0; i < 3; ++i) {score[i] = max(score[i], getscore(i, ch));}}int Max = 0;for(int i = 0; i < 3; ++i) {Max = max(Max, score[i]);++mpp[score[i]];}int cnt = 0;int ans = 0;for(int i = 0; i < 3; ++i) {if(score[i] == Max) {++cnt;ans = i;}}if(cnt >= 2) {printf("Draw\n");} else {switch(ans) {case 0: printf("Kuro\n"); break;case 1: printf("Shiro\n"); break;case 2: printf("Katie\n"); break;}}}return 0;}
在一棵 个节点的树上, 表示从节点 到节点 的一条路径,其中 与 被认为是不同的路径,问有多少条路径不会先经过节点 再经过节点 。
第一行包含三个整数 ,接下去 行每行两个整数 ,表示节点 和节点 之间有一条边,数据保证给出的边集能构成一棵树。
输出合法的路径数量。
| 输入 |
|---|
| 3 1 3 1 2 2 3 |
| 输出 |
| 5 |
| 输入 |
|---|
| 3 1 3 1 2 1 3 |
| 输出 |
| 4 |
将所有路径数 减去不合法的路径数就是答案,不合法路径就是先经过 再经过 的路径,先以 为根 统计 的子树节点数 ,再以 为根 统计 的子树节点数量 ,不合法路径数就是 。
#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <climits>#include <cstring>#include <string>#include <vector>#include <list>#include <queue>#include <stack>#include <map>#include <set>#include <functional>#include <algorithm>using namespace std;#define LL long longconst int maxn = 300000 + 100;LL n;int x, y, u, v;vector<int> G[maxn];int sum[maxn];void dfs(int f, int x) {sum[x] = 1;int len = G[x].size();for(int i = 0; i < len; ++i) {int pos = G[x][i];if(pos != f) {dfs(x, pos);sum[x] += sum[pos];}}}int main() {#ifdef LOCALfreopen("test.txt", "r", stdin);// freopen("10.out", "w", stdout);#endif // LOCALwhile(scanf("%I64d%d%d", &n, &x, &y) != EOF) {for(int i = 1; i <= n; ++i) {G[i].clear();}for(int i = 1; i < n; ++i) {scanf("%d%d", &u, &v);G[u].push_back(v);G[v].push_back(u);}dfs(x, x);LL ans = sum[y];dfs(y, y);ans *= sum[x];printf("%I64d\n", n * (n - 1) - ans);}return 0;}
初始有一个空的集合,有 次操作,每次操作有两种选择:
- 给定 ,表示将 加入到集合中;
- 给定 ,从集合中找到一个整数 ,要求 满足条件 且 的值最大。
第一行为一个整数 ,接下去 行,每行可以是以下两种格式:
- 第一个数字为 ,后面跟着一个整数 ,表示第一种操作;
- 第一个数字为 ,后面跟着三个整数 ,表示操作 。
对于每次操作 ,如果可以找到合法的 ,则输出 的值,否则输出 。
| 输入 |
|---|
| 5 1 1 1 2 2 1 1 3 2 1 1 2 2 1 1 1 |
| 输出 |
| 2 1 -1 |
| 提示 |
| 1.向集合中加入数字 ,则集合为 ; 2.向集合中加入数字 ,则集合为 ; 3. 因此答案为 ; 4.只有 满足前两个条件,因此答案为 ; 5.无法找到满足条件的数字,因此答案为 。 |
| 输入 |
|---|
| 10 1 9 2 9 9 22 2 3 3 18 1 25 2 9 9 20 2 25 25 14 1 20 2 26 26 3 1 14 2 20 20 9 |
| 输出 |
| 9 9 9 -1 -1 -1 |
若 不能整除 ,直接输出 ,如果可以整除,答案就在 的所有倍数中查找,建立 棵字典树,第 棵字典树存的是集合中 的所有倍数,这样每加入一个数字 ,就将 加入到他的所有约数的字典树中,对于每次 操作,直接在第 棵字典树上查找满足条件的答案即可,需要 地预处理所有约数。
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <climits>#include <cmath>#include <string>#include <vector>#include <list>#include <queue>#include <stack>#include <map>#include <set>#include <functional>#include <algorithm>using namespace std;#define LL long longconst int maxn = 100000 + 100;vector<vector<int> > tree;vector<int> Min;int cnt;bool vis[maxn];struct Trie {int root;int creat(int x) {int ret = cnt;++cnt;tree.push_back(vector<int>(2, -1));Min.push_back(x);return ret;}void Init() {root = creat(1000000000);}int id(int x, int Index) {return ((x >> (20 - Index)) & 1);}void add(int x) {int pos = root;Min[pos] = min(Min[pos], x);for(int i = 0; i <= 20; ++i) {int w = id(x, i);if(tree[pos][w] == -1) {tree[pos][w] = creat(x);}pos = tree[pos][w];Min[pos] = min(Min[pos], x);}}int query(int x, int s) {int ret = 0;int num = 0;int pos = root;for(int i = 0; i <= 20; ++i) {int w = !id(x, i);if(tree[pos][w] == -1 || Min[tree[pos][w]] > s) {w = !w;} else {ret |= (1 << (20 - i));}if(tree[pos][w] == -1 || Min[tree[pos][w]] > s) {return -1;}num |= (w << (20 - i));pos = tree[pos][w];}return num;}};int q, command, x, k, s;Trie t[maxn];vector<int> fac[maxn];int main() {#ifdef LOCALfreopen("test.txt", "r", stdin);// freopen("10.out", "w", stdout);#endif // LOCALfor(int i = 1; i < maxn; ++i) {t[i].Init();for(int j = i; j < maxn; j += i) {fac[j].push_back(i);}}scanf("%d", &q);for(int i = 0; i < q; ++i) {scanf("%d", &command);if(command == 1) {scanf("%d", &x);if(vis[x]) {continue;}vis[x] = true;int len = fac[x].size();for(int j = 0; j < len; ++j) {int num = fac[x][j];t[num].add(x);}} else {scanf("%d%d%d", &x, &k, &s);if(x % k != 0 || s <= x) {printf("-1\n");} else {printf("%d\n", t[k].query(x, s - x));}}}return 0;}