Codeforces Round #369 (Div. 2) ABCDE题解
来源:互联网 发布:pfx转jks linux 编辑:程序博客网 时间:2024/05/17 10:03
A. Bus to Udayland
水题,枚举字符并判断,无坑点
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 1e3 + 50;const int MAXM = 5e3 + 50;int n, m;char s[MAXN][10];int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (~scanf("%d", &n)) { bool ok = false; for (int i = 0; i < n; i++) { scanf("%s", s[i]); if (!ok) { if (s[i][0] == 'O' && s[i][1] == 'O') { s[i][0] = s[i][1] = '+'; ok = true; } if (!ok) { if (s[i][3] == 'O' && s[i][4] == 'O') { s[i][3] = s[i][4] = '+'; ok = true; } } } } if (!ok) puts("NO"); else { puts("YES"); for (int i = 0; i < n; i++) printf("%s\n", s[i]); } }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
B. Chris and Magic Square
水题,先记录0出现的位置,然后用已知的行和,求出应该填写的数,再判断是否相等。注意要特判n=1的情况。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 500 + 50;const int MAXM = 5e3 + 50;int n, num[MAXN][MAXN];LL c[MAXN], r[MAXN], d1, d2;int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (~scanf("%d", &n)) { memset(c, 0, sizeof(c)); memset(r, 0, sizeof(r)); d1 = d2 = 0; int x, y; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { scanf("%d", &num[i][j]); if (num[i][j] == 0) { x = i; y = j; continue; } r[i] += num[i][j]; c[j] += num[i][j]; if (i == j) d1 += num[i][j]; if (i + j == n - 1) d2 += num[i][j]; } } if (n == 1) { puts("1"); continue; } LL ans = 0; if (x > 0) ans = r[x - 1] - r[x]; else ans = r[x + 1] - r[x]; r[x] += ans; c[y] += ans; if (x == y) d1 += ans; if (x + y == n - 1) d2 += ans; bool ok = true; LL flag = r[0]; for (int i = 0; i < n; i++) { if (r[i] != flag || c[i] != flag) { ok = false; break; } } if (d1 != flag || d2 != flag) ok = false; if (!ok || ans <= 0) puts("-1"); else printf("%I64d\n", ans); }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
C. Coloring Trees
简单dp,dp[i][j][k]表示第i个位置,颜色为j,段数为k的最小花费。我比较蠢- -,分了4种情况(当前位置和上一个位置是否为0)讨论(比赛时有个细节写错了结果fst。状态转移方程见代码。时间复杂度是O(n*m^2*k),用cf的测评机跑不会超时。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 100 + 50;const int MAXM = 5e3 + 50;int n, m, k, c[MAXN], cost[MAXN][MAXN];LL dp[MAXN][MAXN][MAXN];int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (~scanf("%d%d%d", &n, &m, &k)) { memset(dp, INFLL, sizeof(dp)); memset(cost, 0, sizeof(cost)); for (int i = 1; i <= n; i++) scanf("%d", &c[i]); if (!c[1]) c[0] = 101; else c[0] = c[1]; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { scanf("%d", &cost[i][j]); } } for (int i = 1; i <= m; i++) { dp[0][i][0] = 0; } for (int i = 1; i <= m; i++) { if (c[1]) dp[1][c[1]][1] = 0; else dp[1][i][1] = cost[1][i]; } for (int i = 1; i <= n; i++) { if (c[i]) { if (c[i - 1]) { for (int l = 1; l < i; l++) { if (c[i] == c[i - 1]) dp[i][c[i]][l] = min(dp[i][c[i]][l], dp[i - 1][c[i - 1]][l]); else dp[i][c[i]][l + 1] = min(dp[i][c[i]][l + 1], dp[i - 1][c[i - 1]][l]); } } else { for (int j = 1; j <= m; j++) { for (int l = 1; l < i; l++) { if (c[i] == j) dp[i][j][l] = min(dp[i][j][l], dp[i - 1][j][l]); else dp[i][c[i]][l + 1] = min(dp[i][c[i]][l + 1], dp[i - 1][j][l]); } } } } else { if (c[i - 1]) { for (int j = 1; j <= m; j++) { for (int l = 1; l < i; l++) { if (j == c[i - 1]) dp[i][j][l] = min(dp[i][j][l], dp[i - 1][j][l] + cost[i][j]); else dp[i][j][l + 1] = min(dp[i][j][l + 1], dp[i - 1][c[i - 1]][l] + cost[i][j]); } } } else { for (int j1 = 1; j1 <= m; j1++) { for (int j2 = 1; j2 <= m; j2++) { for (int l = 1; l < i; l++) { if (j1 == j2) dp[i][j1][l] = min(dp[i][j1][l], dp[i - 1][j1][l] + cost[i][j1]); else dp[i][j1][l + 1] = min(dp[i][j1][l + 1], dp[i - 1][j2][l] + cost[i][j1]); } } } } } } LL ans = INFLL; if (c[n]) ans = min(ans, dp[n][c[n]][k]); else for (int i = 1; i <= m; i++) { ans = min(ans, dp[n][i][k]); } printf("%I64d\n", ans == INFLL ? -1 : ans); }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
D. Directed Roads
简单图论+计数。(qwb说的对,确实是水题
题目意思是给你一个可能有环的有向图,你可以翻转一些边(原来u->v变成v->u),使得原图变为一个DAG,输出方案数。
思路比较直接,跑一遍tarjan统计出每个强连通分量的节点数,对于节点数num>2的强连通分量来说,我们必须翻转其中的[1,num-1](也就是(2^num)-2)条边。然后对于其余强连通分量(也就是不属于num>2的scc的节点),我们可选可不选,也就是有2^tmp种情况。然后把以上两种情况的所有结果相乘即可。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e9 + 7;const int MAXN = 2e5 + 50;const int MAXM = 2e5 + 50;int n;struct edge { int to, nxt;} E[MAXM];int Head[MAXN], tot;void edge_init() { tot = 0; memset(Head, -1, sizeof(Head));}void edge_add(int u, int v) { E[tot].to = v; E[tot].nxt = Head[u]; Head[u] = tot++;}/*for (int i = 1; i <= n; i++) if (!DFN[i]) Tarjan(i);*/int Low[MAXN], DFN[MAXN], Stack[MAXN], Belong[MAXN], num[MAXN];int Index, top, scc;bool InStack[MAXN];void Tarjan_init() { memset(DFN, 0, sizeof(DFN)); memset(num, 0, sizeof(num)); memset(InStack, false, sizeof(InStack)); Index = scc = top = 0;}void Tarjan(int u) { int v; Low[u] = DFN[u] = ++Index; Stack[top++] = u; InStack[u] = true; for(int i = Head[u]; i != -1; i = E[i].nxt) { v = E[i].to; if( !DFN[v] ) { Tarjan(v); if( Low[u] > Low[v] )Low[u] = Low[v]; } else if(InStack[v] && Low[u] > DFN[v]) Low[u] = DFN[v]; } if(Low[u] == DFN[u]) { scc++; do { v = Stack[--top]; InStack[v] = false; Belong[v] = scc; num[scc]++; } while( v != u); }}LL fastpow(LL a, LL c) { LL res = 1; while (c) { if (c & 1) res = (res * a) % MOD; a = (a * a) % MOD; c >>= 1; } return res;}int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (~scanf("%d", &n)) { edge_init(); Tarjan_init(); for (int i = 1; i <= n; i++) { int t; scanf("%d", &t); edge_add(i, t); } for (int i = 1; i <= n; i++) if (!DFN[i]) Tarjan(i); LL ans = 1; int tmp = n; for (int i = 1; i <= scc; i++) { if (num[i] > 1) { ans = (ans * (fastpow(2, num[i]) - 2)) % MOD; tmp -= num[i]; } } if (tmp) ans = (ans * fastpow(2, tmp)) % MOD; printf("%I64d\n", ans); }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
E. ZS and The Birthday Paradox
简单数学题。
一年2^n天,求k个人中有人生日是同一天的概率(1<=n,k<=1e18)。
假如一年365天,n个人中有人生日相同的概率为
所以这一题就是让求
然后求出分子分母的gcd约分就可以了。gcd一定是2^x的形式,因为分母已经是2^x的形式,所以只需要求出分子的因子2的个数。
对于1*2*3*...*k,因子2的个数为k/2+k/4+k/8...。
然后求出gcd的逆元,分子分母同时乘上逆元就得到结果了。
#include <map>#include <set>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <string>#include <vector>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;typedef __int64 LL;typedef pair<int,int> PII;#define FIN freopen("in.txt", "r", stdin);#define FOUT freopen("out.txt", "w", stdout);#define lson l, mid, cur << 1#define rson mid + 1, r, cur << 1 | 1#define bitcnt(x) __builtin_popcount(x)#define bitcntll(x) __builtin_popcountll(x)//#pragma comment(linker, "/STACK:1024000000,1024000000")const int INF = 0x3f3f3f3f;const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;const double ERR = 1e-8;const int MOD = 1e6 + 3;const int MAXN = 2e5 + 50;const int MAXM = 2e5 + 50;LL n, k;LL fastpow(LL a, LL c) { LL res = 1; while (c) { if (c & 1) res = (res * a) % MOD; a = (a * a) % MOD; c >>= 1; } return res;}int main() {#ifdef LOCAL_NORTH FIN;#endif // LOCAL_NORTH while (~scanf("%I64d%I64d", &n, &k)) { if (n <= 62 && k > (1LL << n)) { printf("1 1\n"); continue; } LL cnt = 0; LL p = fastpow(2, n); for (LL i = k - 1; i >= 1; i >>= 1) { cnt += i / 2; }// for (LL i = tmp - 1; i >= tmp - k + 1; i--) {// LL ttmp = i & (-i);// cnt += (LL)log2(ttmp);// } LL inv = fastpow(fastpow(2, cnt), MOD - 2); LL up = 1, down = fastpow(p, k - 1); for (LL i = 1; i <= k - 1; i++) { LL tmp = (p - i + MOD) % MOD; up = (up * tmp) % MOD; if (tmp <= 0) //!!! break; } up = up * inv % MOD; down = down * inv % MOD; up = (down - up + MOD) % MOD; printf("%I64d %I64d\n", up, down); }#ifdef LOCAL_NORTH cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // LOCAL_NORTH return 0;}
- Codeforces Round #369 (Div. 2) ABCDE题解
- Codeforces Round #293 (Div. 2) (ABCDE题解)
- Codeforces Round #294 (Div. 2) (ABCDE题解)
- Codeforces Round #296 (Div. 2) (ABCDE题解)
- Codeforces Round #297 (Div. 2) (ABCDE题解)
- Codeforces Round #240 (Div. 2) (ABCDE题解)
- Codeforces Round #313 (Div. 2) (ABCDE题解)
- Codeforces Round #105 (Div. 2) (ABCDE题解)
- Codeforces Round #200 (Div. 2) (ABCDE题解)
- Codeforces Round #186 (Div. 2) (ABCDE题解)
- Codeforces Round #361 (Div. 2) ABCDE题解
- Codeforces Round #360 (Div. 2) ABCDE题解
- Codeforces Round #374 (Div. 2) ABCDE题解
- Codeforces Round #367 (Div. 2) ABCDE 题解
- Codeforces Round #320 (Div. 2) [Bayan Thanks-Round] (ABCDE题解)
- Codeforces Round #198(Div.2)ABCDE
- Codeforces Round #261 (Div. 2)[ABCDE]
- Codeforces Round #264 (Div. 2)[ABCDE]
- 07 设置View的显示与隐藏
- php导出csv文件
- Google 关于 管理Fragment通信的 示例APP 学习
- C复杂声明练习
- 2016年中国的SaaS服务商企业研究
- Codeforces Round #369 (Div. 2) ABCDE题解
- 关于python的列表排序问题汇总
- Android Studio插件整理
- java中线程知识
- OpenCV: Canny边缘检测算法原理及其VC实现详解
- Codeforces Round #369 (Div. 2)解题报告
- 201412-1 门禁系统
- 获取网卡信息
- LintCode(M)打劫房屋2——动态规划