CTS2019D1T1 隨機立方體
阿新 • • 發佈:2022-04-12
做題時:難題啊,我不會啊
看題解:woc,簡單題啊,我咋不會啊
講一下卡住的步驟吧,就是在欽定了極大值的位置和選完數之後,如何算一個類似於十字架的方案。
我們考慮最大值,好的,我們遞迴到了一個子問題,做完了。
CTS2019 都是些什麼神仙題啊!
#include<bits/stdc++.h> using namespace std; #define inf 1e9 const int N=5e6; const int maxn=5e6+10; const int mod=998244353; inline int read(){ int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();} return x*f; } int n,m,l,k,T,f[maxn],g[maxn],c[maxn]; int fac[maxn],ifc[maxn],inv[maxn]; inline int ksm(int x,int y){ int res=1; while(y){ if(y&1)res=1ll*res*x%mod; x=1ll*x*x%mod;y>>=1; }return res; } int main(){ inv[1]=fac[0]=ifc[0]=1; for(int i=2;i<=N;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod; for(int i=1;i<=N;i++)fac[i]=1ll*fac[i-1]*i%mod; for(int i=1;i<=N;i++)ifc[i]=1ll*ifc[i-1]*inv[i]%mod; T=read(); while(T--){ n=read(),m=read(),l=read(),k=read(); int lim=min(min(n,m),l);g[0]=1; for(int i=1;i<=lim;i++) g[i]=1ll*g[i-1]*(n-i+1)%mod*(m-i+1)%mod*(l-i+1)%mod; int all=1ll*n*m%mod*l%mod,now=1,ans=0; for(int i=1;i<=lim;i++) c[i]=all+mod-1ll*(n-i)*(m-i)%mod*(l-i)%mod,now=1ll*now*c[i]%mod; now=ksm(now,mod-2); for(int i=lim;i>=1;i--) f[i]=1ll*g[i]*now%mod,now=1ll*now*c[i]%mod; for(int i=k;i<=lim;i++) if((i-k)&1)ans=(ans-1ll*fac[i]*ifc[k]%mod*ifc[i-k]%mod*f[i])%mod; else ans=(ans+1ll*fac[i]*ifc[k]%mod*ifc[i-k]%mod*f[i])%mod; printf("%d\n",(ans+mod)%mod); } return 0; }