传送门:Problem - 1795D - Codeforces
第一次接触逆元是在学长布置的周赛题,但那时候我没太放在心上,也没有记住学长的模板。今天cf训练的时候又一次碰到了逆元题。最开始本萌新想过把这个进行一个排序,大的数优先。这个数列前一半可以按照最大的数自由发挥,而后一半数列则去填补前一半的有效颜色(依旧选最大权值),使得最终的有效颜色满足题意,但第一个样例都没法算出,有点玄学,我现在还不理解。既然这样,干脆就省去那些细节,直接宏观的去观察。
排列的方式为无序,用,其中b=n/6,a=n/3。这是所选颜色的情况,最后再把个个的可选择数一个一个乘入即可(三个数都相等有三种可能,两个数相等且都为最小数有两种可能)。这时候,就要用到逆元了。感谢大佬的博客:【数论】求逆元的四种方法_辞树c的博客-CSDN博客_求逆元
链接如下:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<string.h>
#include<deque>
#include<set>
typedef long long ll;
using namespace std;
int n,m;
int b[5];
ll mod=998244353;
void nie(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1,y=0;
return;
}
nie(b,a%b,x,y);
ll tmp=x;
x=y;
y=tmp-(a/b)*y;
}
ll ni(ll a){
ll x,y;
nie(a,mod,x,y);
return (x%mod+mod)%mod;
}
ll c(ll x,ll y){
ll ans=1;
while(y){
ans=ans*x%mod;
ans=ans*ni(y)%mod;
x--,y--;
}
return ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie();
cout.tie();
cin>>n;
int q=n/3;
ll ans=1;
while(q--){
cin>>b[1]>>b[2]>>b[3];
sort(b+1,b+4);
if(b[1]==b[3])ans=ans*3%mod;
else if(b[1]==b[2])ans=ans*2%mod;
}
ll u=n/3,o=n/6;
ans=ans*c(u,o)%mod;
printf("%lld",ans);
}