正题
题目大意
有一个\(n\times m\)的网格,在上面填上\([1,k]\)的数字,定义两个长度为\(n\)的序列\(a_i,b_i\)分别表示每一行/每一列的最大值。
求有多少种不同的合法\(a,b\)对。
\(1\leq n,m\leq 10^6,1\leq k\leq 10^9\)
解题思路
不难发现合法的\(a,b\)对只需要满足它们的最大值相等。
那么枚举最大值\(i\),答案就是
\[\sum_{i=1}^k(i^n-(i-1)^n)(i^m-(i-1)^m) \]看到这个式子果断想到这是一个和\(k\)有关的\(n+m+1\)次多项式,又因为\(k\)很大而\(n,m\)很小直接上插值。
时间复杂度:\(O(n\log n)\)(视\(n,m\)同级)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=3e6+10,P=998244353;
ll n,m,k,pwn[N],pwm[N],f[N],inv[N],pre[N],suf[N],ans;
ll power(ll x,ll b){
ll ans=1;
while(b){
if(b&1)ans=ans*x%P;
x=x*x%P;b>>=1;
}
return ans;
}
signed main()
{
freopen("grid.in","r",stdin);
freopen("grid.out","w",stdout);
scanf("%lld%lld%lld",&n,&m,&k);
ll L=n+m+10;
for(ll i=1;i<=L;i++){
pwn[i]=power(i,n);
pwm[i]=power(i,m);
f[i]=(f[i-1]+(pwn[i]-pwn[i-1])*(pwm[i]-pwm[i-1])%P)%P;
}
inv[0]=inv[1]=1;
for(ll i=2;i<N;i++)inv[i]=P-inv[P%i]*(P/i)%P;
for(ll i=1;i<N;i++)inv[i]=inv[i-1]*inv[i]%P;
pre[0]=k;suf[L]=k-L;suf[L+1]=1;
for(ll i=1;i<=L;i++)pre[i]=pre[i-1]*(k-i)%P;
for(ll i=L-1;i>=0;i--)suf[i]=suf[i+1]*(k-i)%P;
for(ll i=0;i<=L;i++){
ll w=f[i]*(i?pre[i-1]:1)%P*suf[i+1]%P;
w=w*inv[i]%P*inv[L-i]%P*(((L-i)&1)?-1:1);
ans=(ans+w)%P;
}
printf("%lld\n",(ans+P)%P);
return 0;
}