题解:需要先推递推公式,发现递推后,直接O(k^2)暴力找就行,注意当r=1的时候,分母为0,需要特判,使用fold筛处理。
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const int maxn = 2e3 + 10;
const ll mod = 1e9 + 7;
ll s[maxn], rr[maxn];
ll fac[maxn], inv[maxn];
ll pow(ll a, ll p, ll MOD) //p=(mod-2)用来求逆元
{
a = a % MOD;
ll ans = 1;
while (p)
{
if (p & 1)
{
ans = (ans*a) % MOD;
}
a = (a*a) % MOD;
p >>= 1;
}
return ans;
}
ll C(int n, int m)
{
return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
void init()
{
fac[0] = inv[0] = 1;
for (int i = 1; i < maxn; i++)
{
fac[i] = fac[i - 1] * i % mod;
inv[i] = pow(fac[i], mod - 2, mod);
}
}
//fold筛
int pv[maxn]; //前几项, 前面无效值用0占位
int st = 1, ed = maxn; //使用上面数组下标为[st,ed]的数据
ll fac_1[maxn + 5], inv_1[maxn + 5], facinv[maxn + 5];
ll pre[maxn + 5], saf[maxn + 5];
void init_fold()
{
fac_1[0] = inv_1[0] = facinv[0] = 1;
fac_1[1] = inv_1[1] = facinv[1] = 1;
for (int i = 2; i < ed + 3; ++i)
{
fac_1[i] = fac_1[i - 1] * i%mod;
inv_1[i] = mod - (mod / i * inv_1[mod%i] % mod);
facinv[i] = facinv[i - 1] * inv_1[i] % mod;
}
}
ll cal(ll x0)
{
int n = ed - st;
x0 = ((x0%mod) + mod) % mod;
pre[0] = ((x0 - st) % mod + mod) % mod;
saf[n] = ((x0 - st - n) % mod + mod) % mod;
for (int i = 1; i <= n; ++i)
{
pre[i] = ((pre[i - 1] * (x0 - st - i)) % mod + mod) % mod;
saf[n - i] = ((saf[n - i + 1] * (x0 - st - n + i)) % mod + mod) % mod;
}
ll res = 0;
for (int i = 0; i <= n; ++i)
{
ll fz = 1;
if (i != 0)fz = fz * pre[i - 1] % mod;
if (i != n)fz = fz * saf[i + 1] % mod;
ll fm = facinv[i] * facinv[n - i] % mod;
if ((n - i) & 1)fm = mod - fm;
(res += pv[i + st] * (fz*fm%mod) % mod) %= mod;
}
return res;
}
int main()
{
int t;
cin >> t;
ll n, k, r;
init(); //打表出组合数
while (t--)
{
cin >> n >> k >> r;
memset(s, 0, sizeof(s));
memset(rr, 0, sizeof(rr));
if (r != 1)//当r不等于1的时候
{
ll inv_ = pow(r - 1, mod - 2, mod);
ll temp_r = pow(r, n + 1, mod);
s[0] = ((pow(r, n + 1, mod) - r % mod + mod) % mod*inv_ + mod) % mod; //求s0,注意r的范围为long long ,直接减会变成很大的负数,需要先取模
for (int i = 1; i <= k; i++)
rr[i] = pow(n, i, mod);
for (int i = 1; i <= k; i++)
{
s[i] = ((temp_r*rr[i] + mod) % mod - r % mod + mod) % mod;
for (int j = 0; j < i; j++)
{
s[i] = (s[i] + C(i, j)*(s[j] - r % mod) % mod*pow(-1, i - j) + mod);
s[i] = s[i] % mod;
}
s[i] = (s[i] * inv_ + mod) % mod;
}
cout << s[k] << endl;
}
else//当r等于1的时候,因为分母不能为0,所以需要特殊计算,使用fold即可
{
memset(pv, 0, sizeof(pv));
for (int i = 1; i <= k+2; i++)
{
pv[i] = pow(i, k, mod) + pv[i - 1] % mod;
}
ed = k + 2;
init_fold();
cout << cal(n) << endl;
}
}
return 0;
}