链接:https://www.nowcoder.com/acm/contest/73/B
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
已知
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)
先说找规律猜公式的方法:
题目中的公式:f[1][1]=1, f[i][j]=a*f[i-1][j]+b*f[i-1][j-1]
不会的话打表找规律呗,然而数据实在是难看出规律,然后仔细看看你会发现:
当a = b = 1的时候f[x][y]不就是组合数C(x-1, y-1)嘛!
(为什么要-1,因为题目中f[1][1]为1其它位置都为0,所以其实错位了,F[1][1]就是C(0, 0))
这样就好办了,这就说明一点:这道题的公式F(n, m)满足当a=b=1时,F(n, m) = C(n-1, m-1)!
也就是说,公式一定是的形式!那么这个时候再根据表猜x和y就OK了(x=n-m, y=m-1)
再说下推公式方法:
a = b = 1的时候f[x][y]是组合数C(x-1, y-1),而组合数C(n, m)其实是(a+b)^n二项式展开后第m+1项的常数
而刚好a=b=1时C(n, m)就是(1+1)^n二项式展开后的第m+1项,也就是说答案就是(a+b)^(n-1)的第m项
#include<stdio.h>
#define LL long long
#define mod 998244353
LL Pow(LL a, LL b);
LL C(LL m, LL n);
LL Lucas(LL m, LL n);
LL inv[100005] = {1}, jc[100005] = {1};
int main(void)
{
LL T, m, n, i, a, b;
for(i=1;i<=100001;i++)
jc[i] = (jc[i-1]*i)%mod;
inv[100001] = Pow(jc[100001], mod-2);
for(i=100000;i>=1;i--)
inv[i] = inv[i+1]*(i+1)%mod;
scanf("%lld", &T);
while(T--)
{
scanf("%lld%lld%lld%lld", &a, &b, &n, &m);
if(n-m<0)
printf("0\n");
else
printf("%lld\n", C(n-1, m-1)*Pow(a, n-m)%mod*Pow(b, m-1)%mod);
}
return 0;
}
LL Pow(LL a, LL b)
{
LL ans;
ans = 1;
while(b)
{
if(b%2==1)
ans = (ans*a)%mod;
a = (a*a)%mod;
b /= 2;
}
return ans;
}
LL C(LL n, LL m)
{
LL ans;
if(n<m)
return 0;
ans = jc[n]*inv[m]%mod*inv[n-m]%mod;
return ans;
}