白兔的式子
题目描述
已知f[1][1]=1,f[i][j]=a*f[i-1][j]+b*f[i-1][j-1](i>=2,1<=j<=i)。
对于其他情况f[i][j]=0
有T组询问,每次给出a,b,n,m,求f[n][m] mod (998244353)
输入描述:
第一行为一个整数T,表示询问个数。
接下来一共T行,每行四个整数a,b,n,m。
输出描述:
一共T行,每行一个整数,表示f[n][m] mod (998244353)
示例1
输入
2
2 3 3 3
3 1 4 1
输出
9
27
思路:手动算几个就能找到规律,对角线以上都是零,其余第 i 行 j 列是(a+b)的(i-1)次方的第 j 个元素,很容易就能确定f[n][m]中a,b的次数,系数是C(n-1)取(m-1)的值,先预处理出阶乘,在用乘法逆元求解。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<list>
#include<queue>
#include<stack>
#include<string>
#include<ctype.h>
#include<sstream>
using namespace std;
const int INF=1<<30;
const double eps=0.00000001;
const double pi=acos(-1);
typedef long long ll;
const int mod=998244353;
ll ksm(ll a,ll b,ll c)
{
ll ans=1;
a=a%c;
while(b>0)
{
if(b%2==1)
ans=(ans%c*(a%c))%c;
b=b/2;
a=((a%c)*(a%c))%c;
}
return ans;
}
int main()
{
ll c[110000];
c[0]=1;
for(ll i=1;i<=100100;i++)
{
c[i]=(i*c[i-1])%mod;
}
int T;
scanf("%d",&T);
while(T--)
{
ll a,b,n,m;
ll ans=0;
scanf("%lld %lld %lld %lld",&a,&b,&n,&m);
if(m==1)
{
ans=ksm(a,n-1,mod);
}
else if(n==m)
{
ans=ksm(b,n-1,mod);
}
else if(n<m)
{
ans=0;
}
else
{
ll tmp1=ksm(a,n-m,mod);
ll tmp2=ksm(b,m-1,mod);
ans=(tmp1%mod)*(tmp2%mod)%mod;
ll sum1=((c[n-1]%mod)*(ksm(c[n-m],mod-2,mod)%mod))%mod;
ll sum2=c[m-1];
ll tmp=((sum1%mod)*(ksm(sum2,mod-2,mod)%mod))%mod;
ans=(ans%mod)*(tmp%mod)%mod;
}
printf("%lld\n",ans);
}
return 0;
}