牛客网 Wannafly挑战赛11 B.白兔的式子-组合数阶乘逆元快速幂

 

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

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)
示例1

输入

2
2 3 3 3
3 1 4 1

输出

9
27

备注:

T<=100000

1<=m<=n<=100000

0<=a,b<=109

 

这个题打个表能发现和杨辉三角有关系,小小了解一下

这个题就是所求位置对应的杨辉三角的系数,然后乘a的幂和b的幂。

因为数很大,不能直接用杨辉三角写,因为杨辉三角的系数也是组合数的阶乘相除,就要用到逆元。

求出来系数之后再用快速幂算一下a的幂和b的幂,就可以了。

 

代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 typedef long long ll;
 8 const int maxn=1e5+10;
 9 const int mod=998244353;
10 ll f[maxn];
11 ll t,a,b,n,m;
12 void ff()
13 {
14     f[0]=1;
15     for(int i=1;i<=100005;i++)
16         f[i]=(i*f[i-1])%mod;
17 }
18 ll poww(ll n,ll m)//快速幂
19 {
20     ll ans = 1;
21     while(m > 0)
22     {
23         if(m & 1)ans = (ans * n) % mod;
24         m = m >> 1;
25         n = (n * n) % mod;
26     }
27     return ans;
28 }
29 ll cc(ll n,ll m)//组合数    阶乘逆元
30 {
31     ll ans=f[n];
32     ans=(ans*poww(f[m],mod-2))%mod;
33     ans=(ans*poww(f[n-m],mod-2))%mod;
34     return ans;
35 }
36 int main(){
37     ff();
38     int t;
39     int a,b,n,m;
40     cin>>t;
41     while(t--){
42         cin>>a>>b>>n>>m;
43         ll xishu=cc(n-1,m-1);
44         ll xa=poww(a,n-m);
45         ll xb=poww(b,m-1);
46         ll ans=((xishu*xa)%mod*xb)%mod;
47         cout<<ans<<endl;
48     }
49 }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 




posted @ 2018-03-17 16:23  ZERO-  阅读(194)  评论(0编辑  收藏  举报