您的位置:首页 > 其它

Wannafly挑战赛11 B-白兔的式子

2018-03-12 09:18 471 查看
链接:https://www.nowcoder.com/acm/contest/73/B
来源:牛客网

题目描述

已知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
[m]=((a+b)^(n-1)式子按a降幂展开的第m项)
套用公式即可。
求逆元时可以用扩展欧几里得求出p[i]*x-mod*y=1的一组解,调整x的值即可。
或用费马小定理求得pow(p[i],mod-2)%mod即可。

扩展欧几里得代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=100007;
const ll mod=998244353;
ll inv[maxn],p[maxn];
ll pow_(ll a,ll b)
{
ll c=1;
while(b)
{
if(b&1)c=c*a%mod;
a=a*a%mod;
b=b/2;
}
return c%mod;
}
ll ex_gcd(ll a,ll b,ll& x,ll& y)
{
ll d=a;
if(b)
{
ex_gcd(b,a%b,y,x);
y-=(a/b)*x;
}
else x=1,y=0;
return d;
}
void init()
{
p[0]=1;
for(ll i=1;i<=100000;i++)p[i]=p[i-1]*i%mod;
for(ll i=0;i<=100000;i++)
{
ll x,y;
ll gcd=ex_gcd(p[i],mod,x,y);
inv[i]=(x+mod)%mod;
}
}
int main()
{
init();
ll T,a,b,n,m;scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld%lld%lld",&a,&b,&n,&m);
n--;
ll c1=pow_(a,n-m+1),c2=pow_(b,m-1);
ll N=((((c1*c2%mod)*p
%mod)*inv[m-1]%mod)*inv[n-m+1]%mod);
printf("%lld\n",N);
}
return 0;
}费马小定理:#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=100007;
const ll mod=998244353;
ll inv[maxn],p[maxn];
ll pow_(ll a,ll b)
{
ll c=1;
while(b)
{
if(b&1)c=c*a%mod;
a=a*a%mod;
b=b/2;
}
return c%mod;
}
void init()
{
p[0]=1;
for(ll i=1;i<=100000;i++)p[i]=p[i-1]*i%mod;
for(ll i=0;i<=100000;i++)inv[i]=pow_(p[i],mod-2)%mod;
}
int main()
{
init();
ll T,a,b,n,m;scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld%lld%lld",&a,&b,&n,&m);
n--;
ll c1=pow_(a,n-m+1),c2=pow_(b,m-1);
ll N=((((c1*c2%mod)*p
%mod)*inv[m-1]%mod)*inv[n-m+1]%mod);
printf("%lld\n",N);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: