题解:P6819 [PA2012] Binary Dodgeball
qczrz6v4nhp6u · · 题解
好玩的题目。
Solution
考虑判定一个局面是先手必胜还是后手必胜。一眼丁真每个棋子都是独立的,所以直接启动
然后发现每个状态的后继都是一个链状的结构,这跟 Nim 游戏是一样的,所以我们知道
枚举每一个值并统计它出现了多少次,推式子:
其中
接下来考虑拆位,即统计
#include<bits/stdc++.h>
using namespace std;
using ui=unsigned int;
using ll=long long;
using ull=unsigned long long;
using i128=__int128;
using u128=__uint128_t;
using pii=pair<int,int>;
#define fi first
#define se second
ull f[6];
void init(){
for(int i=0;i<64;i++)
for(int j=0;j<6;j++)
if(i>>j&1)
f[j]^=3ull<<i;
}
int n;
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
init();
for(int i=0;i<6;i++)
for(int j=0;j<64;j++)
cerr<<(f[i]>>j&1)<<" \n"[j==63];
return 0;
}
打出来的表长这样:
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
不难发现规律:第
对它消元,使得每列仅出现一个
现在我们有相当好的办法刻画
Code
#include<bits/stdc++.h>
using namespace std;
using ui=unsigned int;
using ll=long long;
using ull=unsigned long long;
using i128=__int128;
using u128=__uint128_t;
using pii=pair<int,int>;
#define fi first
#define se second
ui n;bool val[64];
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n;n++;
ull ans=0,cnt=1ull<<29;
for(int i=35;i>=1;i--){
if(!(i&(i-1)))ans|=(ull)val[i]<<i;
else{
if(n>cnt)
n-=cnt,ans|=1ull<<i,val[i&-i]^=1;
cnt>>=1;
}
}
cout<<(ans+(n>1))<<'\n';
return 0;
}