Wannafly交流赛1: B. 白兔的式子(组合数)

链接:https://www.nowcoder.com/acm/contest/73/B
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制: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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值