题目链接:https://www.nowcoder.com/acm/contest/73/B
flag: 找规律 + 逆元解A/B%Mod
找规律不难发现:
* m>n ,f[n][m] = 0;
* m<=n, f[n][m] = C(n-1,m-1)*a^(n-m)*b^(m-1);
主要是C(n-1,m-1)%Mod求有技巧:
C(n-1,m-1)%Mod
= (n-1)!/[(m-1)!*(n-m)!]%Mod
即找出(m-1)! 、(n-m)!的逆元g[m-1]、g[n-m]
= (n-1)!/[g[m-1]*g[n-m]]%Mod
即我们需要预处理出:求出所有i!的逆元与本身(0<=i<=1e5);
而 f[i]定义为i!,g[i]定义为i!的逆元;
我们可以得出:g[i]=g[i+1]*(i+1)%Mod; ( g[i+1]*(i+1)!≡(g[i+1]*(i+1))*i!≡ 1(mod Mod) ,即g[i+1]*(i+1)=g[i]; )
所以我们仅需要求出g[100000],其它均可递推出;
求g[100000],因为Mod=998244353为质数,所以可以非常好用欧拉函数解逆元:x^(Mod-1)≡x*x^≡≡1(mod Mod)
即g[x]=x^(Mod-1) ,可以用快速矩阵幂来处理!
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <vector>
#include <math.h>
#define llt long long
#define Maxn 200010
#define Mod 998244353
using namespace std;
llt f[Maxn],g[Maxn];
llt F(llt x,llt a){
if(a==0)return 1;
if(a==1)return x;
llt ans=F(x,a/2);
if(a%2==0)return ans*ans%Mod;
return ans*ans%Mod*x%Mod;
}
void init(){
f[0]=f[1]=1;
for(int i=2;i<=200000;++i){
f[i]=f[i-1]*i%Mod;
}
g[100000]=F(f[100000],Mod-2);
g[0]=1;
for(int i=100000-1;i>=1;--i)
g[i]=g[i+1]*(i+1)%Mod;
}
int main(){
int T;
init();
scanf("%d",&T);
while(T--){
llt a,b,m,n;
scanf("%lld%lld%lld%lld",&a,&b,&n,&m);
if(m>n)printf("0\n");
else{
printf("%lld\n", f[n-1]*g[m-1]%Mod*g[n-m]%Mod*F(a,n-m)%Mod*F(b,m-1)%Mod);
}
}
return 0;
}