您的位置:首页 > 其它

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

2018-03-10 02:07 309 查看
链接: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
[m] mod (998244353)

输入描述:

第一行为一个整数T,表示询问个数。
接下来一共T行,每行四个整数a,b,n,m。

输出描述:

一共T行,每行一个整数,表示f
[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
*inv[m]%mod*inv[n-m]%mod;
return ans;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: