题目想推导出公式, 还有一点对于T组数据是否可以打表,省时间
公式的推导:多写几个找规律
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 1e6 + 7;
const int mod = 1e9 + 7;
ll T, n, m;
ll jn[N], jm[N], jn_m[N], d[N];
ll fast_pow(ll a, ll b) // 快速幂
{
ll ans = 1, base = a;
while (b)
{
if (b & 1)
{
ans = (ans % mod * base % mod) % mod;
}
base = base * base % mod;
b = b >> 1;
}
return ans;
}
void jc(ll jc[], int n)
{
jc[0] = 1;
for (int i = 1; i <= n; ++i)
{
jc[i] = (jc[i - 1] * i) % mod;
}
}
void unstable(int n)
{
d[0] = 1, d[1] = 0, d[2] = 1, d[3] = 2;
for (int i = 4; i <= N; ++i)
{
d[i] = (d[i - 1] + d[i - 2]) * (i - 1) % mod;
}
}
ll cfny(ll n)
{
ll temp = fast_pow(n, mod - 2) % mod;// 乘法逆元 :a * x 同余 1 (mod p) (x 为乘法逆元 )
// 费马小定理:当 a 是 mod 的倍数是 a 满足: a ^ p 同余 a (mod p)
// 当 a 不是 mod 的倍数 a 的 满足:a ^ (p - 1) 同余 1 (mod p);
// 又可以推导出 :a * x 同余 1 (mod p) , 则 x 为 a 的乘法逆元
// 乘法逆元适用于 a / b % mod
// 用了乘法逆元:a * x % mod = a / b % mod;
// (a + b) % mod = (a % mod + b % mod) % mod;
// (a - b) % mod = (a % mod - b % mod) % mod;
// (a * b) % mod = (a % mod * b * mod) % mod;
// (a / b) % mod = (a % mod / b / mod) % mod;(错误)
// 所以乘法逆元就可以解决此类问题
return temp;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> T;
jc(jn, N), jc(jm, N), jc(jn_m, N);
unstable(N);
while (T--)
{
cin >> n >> m;
ll temp = n - m;
ll ans = (((jn[n] % mod * d[temp] % mod) % mod) * (cfny((jm[m] % mod * jn_m[n - m] % mod) % mod))) % mod;
cout << ans << endl;
}
return 0;
}