@Dmaxiya
2018-08-17T02:26:49.000000Z
字数 6355
阅读 1174
Codeforces
Contests 链接:Codeforces Round #385 (Div. 2)
过题数:4
排名:27/8581
正在学习英语单词,他想要将一个单词通过循环右移得到新的单词,循环右移的方法是:将这个单词的最后一个字符移动到这个单词的第一个字符之前,现在他想要知道,一个单词经过无限次的循环右移,能够得到多少个不同的单词。
一个字符串 ,其中 ,字符串中只有小写字符 'a'-'z'。
输出一个数字,表示将单词 经过任意多次循环右移后得到的不同的单词数量。
| 输入 | 输出 |
|---|---|
| abcd | 4 |
| bbb | 1 |
| yzyz | 2 |
一个字符串只要循环右移 次就能变成它本身,且 很小,用 暴力枚举即可。
#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 <bitset>#include <algorithm>#include <functional>#include <iomanip>using namespace std;#define LL long longstring str, tmp;set<string> st;int main() {#ifdef LOCALfreopen("test.txt", "r", stdin);// freopen("out.txt", "w", stdout);#endif // LOCALios::sync_with_stdio(false);while(cin >> str) {st.clear();int len = str.length();for(int i = 0; i < len; ++i) {st.insert(str);str = str.substr(1, len - 1) + str[0];}cout << st.size() << endl;}return 0;}
很喜欢拼图,现在他有一块长方形的拼图,这块拼图可以用一个 的字符串矩阵来描述,'X' 表示这块地方有图片, '.' 表示这块地方是空的,由于这块拼图太重了,所以 不能旋转、翻转这块拼图。现在给定一块拼图,问能否只通过平移,使得这块拼图的复制品能与原拼图不重叠地拼成一个实心矩形。
第一行包含 和 ,接下来的 行每行有 个字符,所有字符只包含
'.'和'X',含义如题,数据保证所有的'X'在四个方向上是连通的,且至少含有一个'X'。
如果可以拼成一个矩形,则输出 "YES",否则输出 "NO"。
| 输入 | 输出 |
|---|---|
2 3XXXXXX |
YES |
2 2.XXX |
NO |
5 5.......X................. |
YES |
多画几组样例就可以发现,在 全连通的情况下,只有 为一个实心矩形时,才可能将两块拼图不旋转不翻转地拼成一个实心矩形,所以只要找到上下左右最边上的坐标,判断是否实心就可以了。
#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 <bitset>#include <algorithm>#include <functional>#include <iomanip>using namespace std;#define LL long longconst int maxn = 600;int n, m;int minx, miny, maxx, maxy;char str[maxn][maxn];int main() {#ifdef LOCALfreopen("test.txt", "r", stdin);// freopen("out.txt", "w", stdout);#endif // LOCALios::sync_with_stdio(false);while(scanf("%d%d", &n, &m) != EOF) {int cnt = 0;minx = miny = INT_MAX;maxx = maxy = INT_MIN;for(int i = 0; i < n; ++i) {scanf("%s", str[i]);for(int j = 0; j < m; ++j) {if(str[i][j] == 'X') {++cnt;minx = min(minx, i);miny = min(miny, j);maxx = max(maxx, i);maxy = max(maxy, j);}}}if(cnt == 0) {printf("NO\n");continue;}bool flag = true;for(int i = minx; i <= maxx; ++i) {for(int j = miny; j <= maxy; ++j) {if(str[i][j] == '.') {flag = false;break;}}if(!flag) {break;}}if(flag) {printf("YES\n");} else {printf("NO\n");}}return 0;}
是世界的统治者,这个世界上有 个城市和 条道路,这些道路连接任意两个不相同的城市,且任意两个城市之间最多只有一条道路。在这 个城市中有 个城市是首都,为了让这个世界稳定,任意一个两个非首都的城市,如果它们能够到达的首都不相同,那么它们之间就不能有能够互相到达的路径。现在 想要在保证世界稳定的前提下,修建尽可能多的路,问他最多能修建多少条道路。
第一行三个整数 ,第二行有 个不同的整数 ,表示 个首都,接下去 行每行两个整数 ,表示城市 与 之间有一条道路。数据保证世界是稳定的。
输出 在保证世界稳定的前提下,能够修建的最多的道路数。
| 输入 | 输出 |
|---|---|
| 4 1 2 1 3 1 2 |
2 |
| 3 3 1 2 1 2 1 3 2 3 |
0 |
在一个 个节点的连通块内,能修建的最多的道路数为 ,所以可以用并查集判断连通块并统计连通块内的边的数量,对于无法到达首都的那些节点,由于连通块内能连边的道路数是 增长的,所以应尽量使这些节点往有首都的、节点数多的连通块连通,这样才能让可以修建的道路最多。
#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 <bitset>#include <algorithm>#include <functional>#include <iomanip>using namespace std;#define LL long longconst int maxn = 100000 + 100;int n, m, k, ans;int u[maxn], v[maxn];int line[maxn];int sum[maxn];int cap[maxn];int fa[maxn];bool iscap[maxn];void Init() {for(int i = 1; i <= n; ++i) {fa[i] = i;sum[i] = 1;iscap[i] = false;line[i] = 0;}}int Find(int x) {return (x == fa[x]? x: fa[x] = Find(fa[x]));}void unit(int x, int y) {int xx = Find(x);int yy = Find(y);if(xx != yy) {fa[xx] = yy;sum[yy] += sum[xx];}}int main() {#ifdef LOCALfreopen("test.txt", "r", stdin);// freopen("out.txt", "w", stdout);#endif // LOCALios::sync_with_stdio(false);while(scanf("%d%d%d", &n, &m, &k) != EOF) {Init();for(int i = 0; i < k; ++i) {scanf("%d", &cap[i]);}for(int i = 0; i < m; ++i) {scanf("%d%d", &u[i], &v[i]);unit(u[i], v[i]);}int Index = 0;for(int i = 0; i < k; ++i) {cap[i] = Find(cap[i]);iscap[cap[i]] = true;if(sum[cap[i]] > sum[cap[Index]]) {Index = i;}}Index = cap[Index];for(int i = 1; i <= n; ++i) {int f = Find(i);if(!iscap[f]) {unit(f, Index);}}for(int i = 0; i < m; ++i) {int uu = Find(u[i]);++line[uu];}ans = 0;for(int i = 0; i < k; ++i) {ans += (sum[cap[i]] * (sum[cap[i]] - 1)) / 2 - line[cap[i]];}printf("%d\n", ans);}return 0;}
你和 玩一个游戏,首先有一个 的矩阵,如果用 表示这个矩阵中的第 行第 列的数字,则这个矩阵满足
现在你可以问 最多 个问题,每个问题包含 个整数 ,表示要询问的列数, 将会回复你 个整数,第 个整数表示从第 行的所有数字中,选出所有被询问的列的数字中的最小值,即 ,你要通过 的回答来得到每一行除对角线外的最小值,即 。
初始输入只包含一个数字 ,表示矩阵的大小,后面的输入根据你的提问进行回复,每次输入 个数字。
如果你要询问 ,则先输出一个 ,第二行为 个整数,表示要询问的列数,如果你要回答 的问题,则先输出单独的一行 ,第二行输出 个整数,第 个整数表示 。注意在每段输出后清空输出缓冲区。
如果出现下面的情况,你的输出将会返回 :
- 你的输入格式与题目描述不符;
- 你的提问超过了 个;
- 你的问题包含了重复的下标;
- 你的 不在区间 之间;
- 你最后的回答不正确。
| 输入 | 输出 |
|---|---|
| 3 0 0 0 2 7 0 0 0 4 3 0 8 0 5 4 |
3 1 2 3 1 3 2 1 2 1 2 1 1 -1 2 5 4 |
| 2 0 0 0 0 |
1 2 1 1 -1 0 0 |
首先从下标的二进制最低位到最高位枚举(最多只要 次),第 次枚举第 位为 的所有下标,这样就能得到每一行所有下标组合的最小值,由题意可以知道,如果询问的列下标包含 ,则关于 行的回答总是 ,这个回答是不正确的,所以只要将这样的回答筛掉,就可以得到正确的答案。
#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 <bitset>#include <algorithm>#include <functional>#include <iomanip>using namespace std;#define LL long longconst int maxn = 1000 + 100;int n, dig;int Min[maxn], ret[maxn];int ask[maxn], cnt;void get_ask(int d, int x) {cnt = 0;for(int i = 1; i <= n; ++i) {if(((i >> d) & 1) == x) {ask[cnt++] = i;}}}int main() {#ifdef LOCAL// freopen("test.txt", "r", stdin);// freopen("out.txt", "w", stdout);#endif // LOCALios::sync_with_stdio(false);scanf("%d", &n);for(int i = 1; i <= n; ++i) {Min[i] = INT_MAX;}int nn = n;while(nn != 0) {++dig;nn >>= 1;}for(int i = 0; i < dig; ++i) {get_ask(i, 0);printf("%d\n", cnt);for(int j = 0; j < cnt; ++j) {if(j != 0) {printf(" ");}printf("%d", ask[j]);}printf("\n");fflush(stdout);for(int j = 1; j <= n; ++j) {scanf("%d", &ret[j]);if(((j >> i) & 1) != 0) {Min[j] = min(Min[j], ret[j]);}}get_ask(i, 1);printf("%d\n", cnt);for(int j = 0; j < cnt; ++j) {if(j != 0) {printf(" ");}printf("%d", ask[j]);}printf("\n");fflush(stdout);for(int j = 1; j <= n; ++j) {scanf("%d", &ret[j]);if(((j >> i) & 1) != 1) {Min[j] = min(Min[j], ret[j]);}}}printf("-1\n");for(int i = 1; i <= n; ++i) {if(i != 1) {printf(" ");}printf("%d", Min[i]);}printf("\n");fflush(stdout);return 0;}