正题
题目大意
有一个n×mn\times mn×m的网格,在上面填上[1,k][1,k][1,k]的数字,定义两个长度为nnn的序列ai,bia_i,b_iai,bi分别表示每一行/每一列的最大值。
求有多少种不同的合法a,ba,ba,b对。
1≤n,m≤106,1≤k≤1091\leq n,m\leq 10^6,1\leq k\leq 10^91≤n,m≤106,1≤k≤109
解题思路
不难发现合法的a,ba,ba,b对只需要满足它们的最大值相等。
那么枚举最大值iii,答案就是
∑i=1k(in−(i−1)n)(im−(i−1)m)\sum_{i=1}^k(i^n-(i-1)^n)(i^m-(i-1)^m)i=1∑k(in−(i−1)n)(im−(i−1)m)
看到这个式子果断想到这是一个和kkk有关的n+m+1n+m+1n+m+1次多项式,又因为kkk很大而n,mn,mn,m很小直接上插值。
时间复杂度:O(nlogn)O(n\log n)O(nlogn)(视n,mn,mn,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;
}