部分题解
I题 给你一瓶魔法药水:
观察发现,每次操作中两瓶药水的数量减 1 ,另外一瓶药水数量加 1 ,最终结束状态一定是(0,0,1)即两偶一奇,所以一开始奇偶性不同的那种药水一定会被留下来。要做的事情变成使目标药水奇偶性变成与另外两个不同的状态。答案非 1 即 0
#include<bits/stdc++.h> using namespace std; int main() { int a,b,c,x; cin>>a>>b>>c>>x; a%=2,b%=2,c%=2; if(x==2) swap(a,b); else if(x==3) swap(a,c); if(b==c&&a!=b) cout<<0; else cout<<1; }
G题 如果有灵力就好了:
观察发现,符文能否达到一个状态仅与数组的前缀 0 数量与前缀 2 数量有关。我们将 2 看做左括号, 0 看做右括号。合法的符文状态就是一个合法的括号序。于是问题转化为了求合法括号序数量,是个经典的卡特兰数相关问题,我们枚举括号对数,用组合数安排括号分布的位置,再用卡特兰数计算括号序种类,下面的代码提供了O(n)求组合数以及卡特兰数的方法。当然,由于题目数据给的比较小,也可以n^2求组合数,或者用dp求括号序的种类。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=998244353; const int N=1e5+10; ll f[N],g[N],inv[N],H[N]; void init_inverse1() { inv[1]=1; for(int i=2;i<N;i++) inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod; } void init_combinatorial() { init_inverse1(); f[0]=g[0]=1; for(int i=1;i<N;i++) f[i]=(ll)f[i-1]*i%mod; for(int i=1;i<N;i++) g[i]=(ll)g[i-1]*inv[i]%mod; } ll getC(int n,int m) { if(n<m) return 0; return ((ll)f[n]*g[m]%mod)*g[n-m]%mod; } int main() { init_combinatorial(); ll n; cin>>n; ll ans=0; H[0]=1; for(int i=1;i<N-1;i++) H[i]=(4*i-2)*H[i-1]%mod*inv[i+1]%mod; for(int i=0;i<=n/2;i++) { ans+=getC(n,2*i)*H[i]%mod; ans%=mod; } cout<<ans; }
B题 如果有糖果就好了:
这个大家多推一下吧,结果给在下面的代码里了
#include<bits/stdc++.h> using namespace std; int main() { int n; cin>>n; int a=0,b=0; for(int i=1;i<=n;i++) { int x; cin>>x; if(x%2) a++; else b++; } if(a%2==0) cout<<"Alice-Bob"; else if(a%4==3&&b%2==0) cout<<"Bob"; else cout<<"Alice"; }