链接: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[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)的次方展开式的,然后是让你去求第几项是多少
推的的公式是 C(n-1, m-1)%mod*a^(n-m)%mod*b(m-1)%mod 。比赛的时候现学了一波逆元.....
代码示例:
#define ll long long
const ll mod = 998244353;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
ll a, b, n, m;
ll pre[123456];
ll extend_gcd(ll a, ll b, ll &x, ll &y) {
if (b == 0) {
x = 1, y = 0;
return a;
}
else {
ll r = extend_gcd(b, a % b, y, x);
y -= x * (a / b);
return r;
}
}
ll inv(ll a, ll n) {
ll x, y;
extend_gcd(a, n, x, y);
x = (x % n + n) % n;
return x;
}
ll fun(ll x, ll n){
ll res = 1;
while(n > 0){
if (n & 1) res *= x; res %= mod;
x *= x;
x %= mod;
n >>= 1;
}
return res%mod;
}
void init() {
pre[1] = 1; pre[0] = 1;
for(ll i = 2; i <= 100000; i++){
pre[i] = pre[i-1]*i;
pre[i] %= mod;
//printf("%lld ", pre[i]);
}
}
int main() {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int t;
init();
//cout << fun(5, 3) << endl;
//cout << (inv(4, mod)*24)%mod << endl;
cin >> t;
while(t--){
cin >> a >> b >> n >> m;
ll ans = fun(a, n-m);
ans *= fun(b, m-1);
ans %= mod;
n--, m--;
ll f = (pre[m]*pre[n-m])%mod;
ans *= (pre[n]*inv(f, mod))%mod;
printf("%lld\n", ans%mod);
}
return 0;
}