比賽鏈接 上紫啦hhh,好開心 每個題裡面都有中文翻譯,我就不說題意了。。 A 直接模擬即可 #include<cstdio> #include<algorithm> #define int long long using namespace std; const int MAXN = 1e5 + ...
比賽鏈接
上紫啦hhh,好開心
每個題裡面都有中文翻譯,我就不說題意了。。
A
直接模擬即可
#include<cstdio> #include<algorithm> #define int long long using namespace std; const int MAXN = 1e5 + 10; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int T; int a[MAXN], pos, Q, N; main() { T = read(); while(T--) { N = read(); pos = read(); Q = read(); for(int i = 1; i <= N; i++) a[i] = i; while(Q--) { int x = read(), y = read(); swap(a[x], a[y]); } for(int i = 1; i <= N; i++) if(pos == a[i]) { printf("%d\n", i); break; } } }A
B
這題我交了五遍沒過,捂臉,然而並不知道自己哪裡錯了
跟lyq說了說還被婊了一頓。。。。最後換了個寫法A了。。
直接大力特判就行,至於哪個share什麼玩意兒就讓N-1,M-1,然後判是否可行
#include<cstdio> using namespace std; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N, M, X, Y; int pd(int N, int M) { /*if(N == 0 && M == 0) return 1; else if((N < X) || (M < Y)) return 0; else if(N % X == 0 && M % Y == 0) return 1; else return 0;*/ if(N < 0 || M < 0) return 0; return N % X == 0 && M % Y == 0; } int main() { int T; scanf("%d", &T); while(T--) { N = read(), M = read(), X = read(), Y = read(); N--; M--; if(pd(N, M)) {puts("Chefirnemo"); continue;} N--; M--; if(pd(N, M)) {puts("Chefirnemo"); continue;} puts("Pofik"); } return 0; }B
C
這題就有點厲害了!
結論:哥德巴赫猜想在信息學奧賽的範圍內是成立的!
也就是說,任意一個$>=4$的偶數都是合法的。
然後把奇數和$0$判掉,維護出$0, 1$的個數即可
#include<cstdio> #define LL long long using namespace std; const int MAXN = 1e6 + 10; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int T; int N; int a[MAXN]; LL tim[MAXN]; LL calc(LL x) { return x * (x - 1) / 2; } int main() { // printf("%d", 2 ^ 4); T = read(); while(T--) { N = read(); for(int i = 1; i <= N;i ++) a[i] = read(), tim[a[i]]++; LL ans = 0, ze = 0, on = 0; /*for(int i = 1; i <= N; i++) { for(int j = i + 1; j <= N; j++) { int x = (a[i] ^ a[j]); if((!(x & 1)) && (x != 2) && (x != 0)) ans++; } }*/ for(int i = 1; i <= N; i++) if(a[i] & 1) on++; else ze++; ans = calc(ze) + calc(on); //printf("%d\n", ans); LL a1 = 0; for(int i = 1; i <= N; i++) a1 += tim[a[i] ^ 2]; ans -= a1 / 2; for(int i = 1; i <= N; i++) { ans -= (tim[a[i]] * (tim[a[i]] - 1)) / 2, tim[a[i]] = 0; } printf("%lld\n", ans); } return 0; }C
D
爆搜打出前$8$的表,不難找到規律:
最小的一定是$n, 1, 2, 3, \dots n - 1$
最大的是:$2, 3, 4, 5, n / 2, 1, 2 + n / 2, 3 + n / 2, 4 + n /2 ...$
奇數的話還要特殊考慮一下倒數第二位
#include<cstdio> #include<map> #include<iostream> #define ull unsigned long long #define LL long long using namespace std; const int MAXN = 1e6 + 10, INF = 1e9 + 7; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N; int ans[MAXN], num; int main() { // freopen("a.out", "w", stdout); N = read(); for(int i = 2; i <= N / 2; i++) ans[++num] = i; ans[++num] = 1; for(int i = 2; i <= N / 2; i++) ans[++num] = N / 2 + i; ans[++num] = 1 + N / 2; for(int i = 1; i <= num - 1; i++) printf("%d ", ans[i]); if(N & 1) printf("%d ", N); printf("%d\n", ans[num]); printf("%d ", N); for(int i = 1; i <= N - 1; i++) printf("%d ",i); return 0; }D
E
首先考慮暴力怎麼打,我們把給出的初始行列的01取反,這樣$0$的時候對應的是必勝態,$1$對應的是必敗態。
然後按博弈論的定義推,$(i, j)$若是必勝態,那麼至少有$(i - 1, j)$是必敗態 或者 $(i, j - 1)$是必敗態。
然後暴力枚舉一遍就行了,複雜度$O(NM)$
接下來的操作就比較神仙了,,打表 或 直接觀察式子可得,若第$(i, j)$個點是必敗點,那麼它所在的對角線往後的點,都是必敗點!
這樣我們就把狀態降到了$2 * M$
那最開始的必敗點怎麼求呢?
直覺告訴我們 稍加證明不難得到,這種點一定是出現在前兩行 或者前兩列。
然後就做完了。
暴力推前兩行 前兩列即可。
保險起見我推了三行三列。
#include<cstdio> #include<cstring> #include<vector> #define LL long long using namespace std; const int MAXN = 1e5 + 10; inline LL read() { char c = getchar(); LL x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int T; int a[4][MAXN], b[MAXN][4], N, M, f[MAXN], g[MAXN]; char A[MAXN], B[MAXN]; int main() { //- freopen("a.out", "w", stdout); int T = read(); while(T--) { scanf("%s", A + 1); scanf("%s", B + 1); M = strlen(A + 1); N = strlen(B + 1); for(int i = 1; i <= M; i++) a[0][i] = (A[i] == '1' ? 0 : 1); for(int i = 1; i <= 3; i++) a[i][0] = (B[i] == '1' ? 0 : 1); for(int i = 1; i <= 3; i++) b[0][i] = (A[i] == '1' ? 0 : 1); for(int i = 1; i <= N; i++) b[i][0] = (B[i] == '1' ? 0 : 1); memset(f, 0x7f, sizeof(f)); memset(g, 0x7f, sizeof(g)); for(int i = 1; i <= 3; i++) { for(int j = 1; j <= M; j++) { if(a[i - 1][j] == 1 || a[i][j - 1] == 1) a[i][j] = 0;//能到達必敗節點的 else a[i][j] = 1; if(a[i][j] == 1) f[j - i + 1] = min(f[j - i + 1], i); } } for(int i = 1; i <= N; i++) { for(int j = 1; j <= 3; j++) { if(b[i - 1][j] == 1 || b[i][j - 1] == 1) b[i][j] = 0; else b[i][j] = 1; if(b[i][j] == 1) g[i - j + 1] = min(g[i - j + 1], j); } } vector<int> ans; int Q = read(); while(Q--) { int x = read(), y = read(); int dy = y - x + 1, dx = x - y + 1; if(dy >= 1) { if(x >= f[dy]) ans.push_back(0); else ans.push_back(1); } else { if(y >= g[dx]) ans.push_back(0); else ans.push_back(1); } } for(int i = 0; i < ans.size(); i++) printf("%d", ans[i]); puts(""); } return 0; }E
F
這個題我就不說啥了,challenge題嘛,xjb亂搞。
但是!!!
我TM辛辛苦苦寫了半天的貪心324分??
直接輸出$1$有400+????????????