掉大分+自闭场QAQ
A. And Then There Were K
随便瞎搞一个数
10111000
1
(
2
)
101110001_{(2)}
101110001(2),然后递减对齐观察。
1011
1
000
[
1
]
(
2
)
1011\;1\;000[1]_{(2)}
10111000[1](2)
1011
[
1
]
000
[
0
]
(
2
)
1011[1]000[0]_{(2)}
1011[1]000[0](2)
1011
[
0
]
111
1
(
2
)
1011[0]111\;1_{(2)}
1011[0]1111(2)
…
[
1
]
0000000
0
(
2
)
[1]00000000_{(2)}
[1]00000000(2)
[
0
]
1111111
1
(
2
)
[0]11111111_{(2)}
[0]11111111(2)
显然找到最高位的1后再-1后的&结果为0。一开始暴力求解t了一次,我菜死了呜呜
void solves(){
int n;cin>>n;
int ans=1;
while(ans<=n) ans*=2;
ans/=2;
cout<<ans-1<<endl;
}
B1. Palindrome Game (easy version)
思维受限了,一个多小时里对自己的假思路深信不疑。。我好傻QAQ
详细阐述一下必败态。
我们记0的个数为cnt,
1.cnt=1时BOB win
2.cnt为奇数(cnt!=1)时,只要ALICE先选取中间的0(第一步选取非中间的0是必败态),无论BOB选取哪个,ALICE都能选取和它对称的那个0。一直到剩下最后的一对0,此时ALICE反转操作即可。
举个栗子:00000
A 00100
B 01100
A 01110
B 11110
A reverse
B 11111
3.cnt为偶数时,BOB可以不停选取和ALICE所选取的对称的0,一直到剩下最后一对0,此时BOB进行反转操作即可。举个栗子:000000
A 100000
B 100001
A 110001
B 110011
A 111011
B reverse
A 111111
其实讲了这么多,我只是想表达这个sb题的必败态就是先选取有对称0的那个。。cnt=1的时候没有对称0,后手胜。cnt为奇数时,先手选取中点,后手不得不选取先对称0,导致先手必胜。cnt为偶数时,先手不得不先选取对称0,导致后手必胜。
void solves(){
int n;cin>>n>>s;
int cnt=0;
for(auto x:s){
if(x=='0') cnt++;
}
if(cnt&1){
if(cnt==1)cout<<"BOB\n";
else cout<<"ALICE\n";
} else{
cout<<"BOB\n";
}
}
B2. Palindrome Game (hard version)
这里我们只对一开始为非回文串进行讨论。
先给出结论。记 将非回文串变为回文串的最少改变的0的个数为cnt,记通过最少改变次数后的回文串的0的个数为o。当cnt=1且o=1时,ALICE和BOB是平手,其他情况都是ALICE胜利。
结论有比较详细的讨论证明,但是有点太长了,我不想写了(真的太长不想写,有兴趣的话可以私信一起交流)。这里就简单提一下分析的思路QAQ
我们记ALICE的花费为A,BOB的花费为B。在easy version分析必败态的时候我们知道,当最初的string是回文时(ALICE先手),两人都使用最优策略的情况下,当0的个数为1时,有【A=1,B=0】;当0的个数是偶数时,有【B+2=A】;0的个数为奇数是,有【A+1=B】。
显然,我们发现当一开始都为回文串的时候,两人在使用最优策略的情况下,二者花费的差值不超过2。那么我们可以对cnt=1,cnt=2,cnt>2来进行讨论。
当cnt=1时,有…(自己讨论一下先后手。只有当o=1时是DRAW,其他情况都是ALICE win)
cnt=2,有…(自己讨论一下先后手,反正讨论完的结果都是ALICE win)
cnt>2时,显然都是ALICE win。
void solves(){
int n;cin>>n>>s;
int cnt=0;
int o=count(s.begin(),s.end(),'0');
for(int l=0,r=n-1;l<r;++l,--r){
if(s[l]!=s[r]) cnt++;
}
o-=cnt;
if(!cnt){
if(o&1){
if(o==1)cout<<"BOB\n";
else cout<<"ALICE\n";
} else{
cout<<"BOB\n";
}
} else{
if(!o){
cout<<"ALICE\n";return ;
}
if(cnt==1){
if(o==1) cout<<"DRAW\n";
else cout<<"ALICE\n";
} else{
cout<<"ALICE\n";
}
}
}
C. Sequence Pair Weight
想想每对pair都会在哪些区间上
void solves(){
int n;cin>>n;
ll ans=0;
map<ll,ll>mp;
for(int i=0;i<n;++i){
int x;cin>>x;
ans+=mp[x]*(n-i);
mp[x]+=(i+1);
}
cout<<ans<<endl;
}