这题在多校现场,才22队出。虽然最后结果是25个队,但是有三个队是随机数过的,是的,全凭运气。
为什么我知道呢,因为第一个用随机数A掉的就是我……
官方题解:
这是本场比赛最大的坑题.
首先, 棋盘就是一个二分图, 可以得出任意一个Meditation (u,v)和任意一个pollutant (a,b), u+v和u−v就是把曼哈顿距离写成了切比雪夫距离而已...
剩下的部分就是一个简单的阶梯博弈. 把所有和Meditation的曼哈顿距离为偶数的点的水晶数异或起来, 如果为0则lose, 否则win.
这里的阶梯博弈证明就是, 对于先手, 如果上面方法算出来的sg值大于0, 那么按照nim取石子游戏的步骤一样, 把某个奇点(和Meditation曼哈顿距离为偶数的点)移到偶点. 如果对面选择把偶点移到奇点, 由于奇点是不存在pollutant的, 所以水晶数不会减少, 那么这时候先手只需要把同样数量的水晶从奇点移到偶点即可.
如果得到的值是0, 那么就变成一个对方先手且sg不为0的情况, 所以此时先手必败.
正确的AC方式(来自
http://blog.youkuaiyun.com/cantsayaword/article/details/77370443):
#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 500005;
pair<int,int> med[N],pol[N];
struct Ct{
int x,y,w;
Ct(){}
Ct(int x,int y,int w):x(x),y(y),w(w){}
};
vector<Ct>c;
int main(){
int T,n,m,k,x,y,w,t,s,mx;
scanf("%d",&T);
while(T--){
mx=0;
scanf("%d %d %d",&n,&m,&k);
c.clear();
for(int i=1;i<=k;i++){
scanf("%d %d %d",&x,&y,&w);
c.push_back(Ct(x,y,w));
}
scanf("%d",&t);
for(int i=1;i<=t;i++){
scanf("%d %d",&med[i].first,&med[i].second);
if(med[i].first==n)
mx=max(mx,med[i].second);
}
scanf("%d",&s);
for(int i=1;i<=s;i++)
scanf("%d %d",&pol[i].first,&pol[i].second);
int ans=0;
for(int i=0;i<k;i++){
if(c[i].x<n&&(abs(c[i].x-n+1)+abs(c[i].y-m))%2==0)
ans^=c[i].w;
else if(c[i].x==n&&c[i].y<=mx&&abs(c[i].y-mx)%2==0)
ans^=c[i].w;
}
puts(ans?"win":"lose");
}
return 0;
}
我的随机输出写法(别试了,想通过,很难的):
#include<map>
#include<set>
#include<list>
#include<stack>
#include<deque>
#include<queue>
#include<vector>
#include<sstream>
#include<iomanip>
#include<iostream>
#include<math.h>
#include<ctype.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<functional>
#define CPY(A,B)memcpy(A,B,sizeof(A))
#define fin freopen("in.txt","r",stdin)
#define fout freopen("out.txt","w",stdout)
typedef long long LL;
typedef unsigned long long uLL;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
const LL INFF=0x3f3f3f3f3f3f3f3fLL;
const double OO=1e20;
const double EPS=1e-9;
const double PI=acos (-1.0);
int dx[]= {0,1,0,-1};
int dy[]= {1,0,-1,0};
using namespace std;
int gcd (const LL &a,const LL &b) {
return b==0?a:gcd (b,a%b);
}
inline int dcmp (double a,double b) {
if (fabs (a-b) <EPS) { return 0; }
return a<b?-1:1;
}
const int M=30030;
int main() {
int T;cin>>T;
srand((unsigned)time(NULL));
while(T--){
(rand()%2==0)?puts("lose"):puts("win");
}
return 0;
}