逆元 + 快速幂
链接: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; }
东北日出西边雨 道是无情却有情