上紫啦hhh,好开心
每个题里面都有中文翻译,我就不说题意了。。
直接模拟即可
#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;
}
}
}
这题我交了五遍没过,捂脸,然而并不知道自己哪里错了
跟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;
}
这题就有点厉害了!
结论:哥德巴赫猜想在信息学奥赛的范围内是成立的!
也就是说,任意一个$>=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;
}
爆搜打出前$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;
}
首先考虑暴力怎么打,我们把给出的初始行列的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;
}
这个题我就不说啥了,challenge题嘛,xjb乱搞。
但是!!!
我TM辛辛苦苦写了半天的贪心324分??
直接输出$1$有400+????????????