[题解]LGR-180 Div.3 B&C
两道趣题。
(抽象的是\(C\)是原题,HDU2147,巴什博弈)
T2 ChS
赛时思路
一开始想的是用排列组合做,但是发现表示状态太麻烦,所以就想到做减法。
用\(fac\)表示总个数\(26^n\);用\(c1\)表示一个\(ab\)都没有的个数\(24^n\);用\(c2\)表示至少包含一个\(a\)的个数\(fac-25^n\)(即\(总数-一个a没有的\))。
偶然发现有点容斥的味道,答案就是\(c1-2*c2-fac\)。
题解思路
先写出总个数:\(26^n\)。
然后,\(a\)和\(b\)都不包含的个数:\(24^n\)。
再表示出没有\(a\)和没有\(b\)的个数:都是\(25^n\)。
也是容斥,答案为\(26^n-2*25^n+24^n\)。
注意
- 别忘取模。
- 开
long long
。 - 需要注意的是,做了减法运算可能得出负数,而负数再取模会发生问题,所以可以用以下方法解决:
- 赛时:手写一下\(mod\),使取模的结果非负(调了我半天呜呜呜)。
- 题解:直接加一个\(mod\)再模,因为考虑最坏情况\(0-998244352=-998244352\),所以加一个就能保证非负了(题解加了\(10*mod\),一样的效果,但别加太多,小心超
long long
)。
Code
赛时Code
#include<bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std;
int T,n;
int qpow(int base,int power){
int fac=1;
while(power){
if(power&1) fac=fac*base%mod;
base=base*base%mod;
power>>=1;
}
return fac;
}
int mo(int A,int B){
int t=A%B;
if(t<0) return t+B;
return t;
}
signed main(){
cin>>T;
while(T--){
cin>>n;
int fac=qpow(26,n);
int c1=qpow(24,n),c2=fac-qpow(25,n);
//c1表示一个ab都没有,c2表示至少一个a的个数;
cout<<mo(c1+2ll*c2%mod-fac,mod)<<endl;
}
return 0;
}
题解Code
#include<bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std;
int T,n;
int qpow(int base,int power){
int fac=1;
while(power){
if(power&1) fac=fac*base%mod;
base=base*base%mod;
power>>=1;
}
return fac;
}
signed main(){
cin>>T;
while(T--){
cin>>n;
cout<<(qpow(26,n)-2*qpow(25,n)+qpow(24,n)+mod)%mod<<endl;
}
return 0;
}
T3 Game
题解的思路是通过暴力程序找规律(\(N,M\leq 10^{18}\)没规律也不正常),就不放了。
赛时思路
经过一番思考,得到结论:都按完美策略发挥的情况下,先碰到上或右板边的一方必胜。
为什么呢?因为碰到上或右板边,就只能轮流往一个方向走了。举个例子,现在棋子在第二行,该你走棋,那么你应当让他碰到上边,但是具体应该向上走,还是向右上走,就要看目前到右板边的距离的奇偶性了。总之知道了这个结论就可以了,我们继续。
要想让我们先到达板边,就要让到右和上的距离都为偶数。这样,对方走一步,我走一步,一定是我先抵达。就这样,我们得出了结论,第一步要让到右边和到上边的距离都为偶数。
具体实现见代码。
赛后思考
也有另一种思考方式:我们每走完一步,都要让棋子到上板边和右半边的距离都是偶数。这样,对方无论怎么走,我们都能重新调整到这个状态。最后就可以达到终点(距离都为\(0\))。
Code
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,n,m;
signed main(){
cin>>t;
while(t--){
cin>>n>>m;
if(n%2==1){
if(m%2==1) cout<<"-1\n";
else cout<<"1\n";
}else{
if(m%2==1) cout<<"2\n";
else cout<<"3\n";
}
}
return 0;
}