CF996
A
link

如果两只小动物只往中间跳的话,那么中间间隔奇数个就是另一个小动物赢(一定会出现两个小动物挨着而该爱丽丝跳了),否则就是爱丽丝赢(一定会出现两个小动物挨着而改另一个动物跳了)。
那么我们可以发现,两个小动物只会往中间跳,因为往边上跳跳出去再跳回来一定是偶数步,不会改变自己的输赢(即不改变奇偶性)。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,a,b;
void qwq(){
cin >> n >> a >> b;
if(a%2 == b%2) cout << "YES\n";
else cout << "NO\n";
}
signed main(){
int _;
cin >> _;
while(_--) qwq();
return 0;
}
B
link

如果我们选了\(i\)又选了\(j\),一定不优,因为(不妨设\(i<j\))原数组会变成
\(a_1-2,a_2-2……a_{i-1}-2,a_i,a_{i+1}-2……a_{j-1}-2,a_j,a_{j+1}-2……a_{n-1}-2,a_n-2\)(不难得出,手推一下即可)。
所以我们一定只改变一个,那么我们首先看看我们需要改变几个,如果是一个,再看看其它数多出的能否满足它的需求。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n;
int a[200005];
int gs,wz;
int b[200005];
void qwq(){
cin >> n;
gs = 0;
for(int i = 1;i <= n;++ i)
cin >> a[i];
for(int i = 1;i <= n;++ i){
cin >> b[i];
if(b[i] > a[i]) gs++,wz = i;
}
if(gs >= 2) cout << "NO\n";
else if(gs == 0) cout << "YES\n";
else{
for(int i = 1;i <= n;++ i){
if(i != wz&&a[i]-b[wz]+a[wz] < b[i]){
cout << "NO\n";
return;
}
}
cout << "YES\n";
}
}
signed main(){
int t;
cin >> t;
while(t--) qwq();
return 0;
}
C
link

我们设每一行每一列的和为\(x\),那么有\(xn=xm\),当\(n!=m\)的时候,\(x\)只有等于\(0\)才能满足条件。
那么我们就让每一行每一列的和为\(0\)去求空着的。
怎么求呢?(设当前在位置\(x,y\))我们知道,如果下一步要往右边走,那么一定不会再走到左边(即第\(1~y\)列),那么第\(1~y\)列的数除了这个都已经确定了,那么我们可以根据每一列的和为\(0\)求出该点;下一步往下走同理。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m;
char s[2005];
int a[1005][1005];
int sum[2][1005];
void qwq(){
cin >> n >> m;
cin >> s+1;
for(int i = 1;i <= n;++ i){
for(int j = 1;j <= m;++ j){
cin >> a[i][j];
sum[0][i] += a[i][j];
sum[1][j] += a[i][j];
}
}
int x = 1,y = 1;
for(int i = 1;i <= n+m-2;++ i){
if(s[i] == 'R'){
a[x][y] = 0-sum[1][y];
sum[0][x] += a[x][y];
sum[1][y] += a[x][y];
y++;
}
else{
a[x][y] = 0-sum[0][x];
sum[0][x] += a[x][y];
sum[1][y] += a[x][y];
x++;
}
}
a[n][m] = 0-sum[0][n];
sum[0][n] += a[n][m];
sum[1][m] += a[n][m];
for(int i = 1;i <= n;++ i){
for(int j = 1;j <= m;++ j)
cout << a[i][j] << " ";
cout << endl;
}
}
signed main(){
int _;
cin >> _;
while(_--) qwq();
return 0;
}
D
link

真不如去看这个。。。
一个大模拟,看注释吧。。。
在注释中可能有一些话难以理解,我会在那句话后面画一个括号对应到上面来。
(1)大家可能对这里的加/减\(tim\)不太理解,这里我们过去了\(tim\)秒,但是我们前面并没有管后面的稻草人,其实他们在这些时间里也是移动的。
(2)推着:因为乌鸦要和稻草人保持\(k\)的距离,所以我们可以认为一个离乌鸦正好为\(k\)的稻草人,它往前一步,乌鸦也往前一步,所以我们可以认为稻草人是在推着乌鸦走。而前面的稻草人是不可能距离乌鸦小于\(k\)的,由于我们的算法,他也不会大于\(k\)。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,k,l;
int a[200005];
void qwq(){
cin >> n >> k >> l;
k *= 2;l *= 2;
for(int i = 1;i <= n;++ i)
cin >> a[i],a[i] *= 2;
//为了避免分数,让所有涉及到时间的都乘2
int x = 0;
//乌鸦位置
int at = 1;
//乌鸦前面离他最近的稻草人的编号
int tim = 0;
//时间
while(at+1 <= n&&a[at+1] == 0) at++;
//去除前面都在零的那些稻草人
if(a[1] > 0){
tim += a[1];
a[1] = 0;
//首先让最前面的稻草人到0的位置和乌鸦重合
//(这里不理解先看后面
}
while(1){
x = a[at]+k;
//重合了,乌鸦传到了当前位置+k
//(因为重合了,当前位置就是a[at]
if(x >= l) break;
//如果已经到达l了,退出
//每次的目的:
//让乌鸦后面里乌鸦最近的稻草人和乌鸦重合
if(at+1 <= n){
//如果乌鸦后面还有稻草人
//(1)
if(a[at+1]-tim > x){
//如果在前面的时间里一直往前走
//也无法和x重合
//那么我们就再用一些时间让他们两个重合
tim += (a[at+1]-tim-x)/2;
//为什么除以2呢?
//因为在乌鸦前面的稻草人可以推着他
//往后走,去找稻草人(2)
at++;
a[at] -= tim;
//一直往前走(走了时间这么多,减去时间
}
else if(a[at+1]+tim >= x){
//乌鸦在这个稻草人往前走的范围内
//也在往后走的范围内
//说明稻草人可以走到乌鸦的位置
//那就让稻草人在乌鸦的位置
at++;
a[at] = x;
}
else{
//否则,让稻草人往后走到
//当前时间内能走到的位置
at++;
a[at] += tim;
}
}
else{
//乌鸦后面没有稻草人了
tim += l-x;
//前面那个稻草人推着乌鸦往前走l-x个位置(2)
//从x(当前位置)走到l
break;
}
}
cout << tim << endl;
}
signed main(){
int t;
cin >> t;
while(t--) qwq();
return 0;
}

浙公网安备 33010602011771号