**
**
8.0 秒 131,072.0 KB 1280 分 9级题
T(n) = n^k,S(n) = T(1) + T(2) + … T(n)。给出n和k,求S(n)。
例如k = 2,n = 5,S(n) = 1^2 + 2^2 + 3^2 + 4^2 + 5^2 = 55。
由于结果很大,输出S(n) Mod 1000000007的结果即可。
输入
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 500)
第2 - T + 1行:每行2个数,N, K中间用空格分割。(1 <= N <= 10^18, 1 <= K <= 50000)
输出
共T行,对应S(n) Mod 1000000007的结果。
输入样例
3
5 3
4 2
4 1
输出样例
225
30
10
首先看第一种方法根据差分法的定义
**自然数幂和一定可以构成一个k+1次的多项式(若次方数为k)
所以可以先求出前k+2项的函数值 由于 k+2个点必定可以确定一条最高次幂为k+1次方的函数
所以此时可以直接套用拉格朗日插值求出第n项 **
注意的是当n比较大时 i^k%mod必定为零所以n%=mod可以减少时间
插值法代码:
#include
using namespace std;
typedef long long ll;
const int maxn = 5e4 + 5;
const int N = 5e4;
const int mod = 1e9 + 7;
ll Pow(ll x, ll y, ll mod){
ll res = 1;
while (y){
if (y & 1) res = res*x%mod;
y >>= 1;
x = x*x%mod;
}
return res;
}
ll fac[maxn], f[maxn], n, k;
void init(){ //sgm(i^k)求和的第n项
fac[0] = 1; f[0] = 0;
for (int i = 1; i <= N; i++){
fac[i] = fac[i - 1] * i%mod;//阶乘
//f[i] = (f[i - 1] + Pow(i, k, mod)) % mod;//前k项的函数值y
}
}
ll p[maxn], q[maxn];//正反求分母的式子
ll solve(ll n, ll k){
ll ans = 0;
p[0] = q[k + 3] = 1;
for (int i = 1; i <= k + 2; i++) p[i] = p[i - 1] * (n - i) % mod;
for (int i = k + 2; i >= 1; i--) q[i] = q[i + 1] * (n - i) % mod;
for (int i = 1; i <= k + 2; i++){
ll x = (k - i + 2) % 2 ? (-1) : 1;
ll num = f[i] * p[i - 1] % mod * q[i + 1] % mod;//函数值乘分子
ll c=Pow(fac[i - 1] * fac[k - i + 2] % mod, mod - 2, mod) % mod;//分母
ans = (ans + (num*c%mod*x%mod + mod) % mod) % mod;
}
return ans;
}
int main(){
init();
int T;
cin >> T;
while (T--){
scanf("%lld%lld", &n, &k);
n %= mod;
for (int i = 1; i <= k + 2; i++)
f[i] = (f[i - 1] + Pow(i, k, mod)) % mod;//前k项的函数值y
printf("%lld\n", solve(n, k));
}
return 0;
}
用ntt多项式求逆做法:
#include
using namespace std;
typedef long long ll;
const int G = 3, mod = 1e9 + 7, N = (1<<17);// mod 998244353
int n, len, a[N], rev[N];
int B[N], f[N], inv[N], c[N];
const int mod1 = 998244353, mod2 = 469762049, mod3 = 1004535809;
int m[3] = { mod1, mod2, mod3 };
ll M = 1ll * mod1*mod2;
ll Pow(ll x, ll y, ll mod){
ll res = 1;
while (y){
if (y & 1) res = res*x%mod;
y >>= 1;
x = x*x%mod;
}
return res;
}
ll mul(ll x, ll y, ll mod){
ll res = 0;
while (y){
if (y & 1) res = (res + x) % mod;
x = x * 2 % mod;
y >>= 1;
}
return res;
}
ll C(ll n, ll m){
if (m > n) return 0;
return 1ll*f[n] * inv[n - m] % mod*inv[m] % mod;
}
void NTT(int n, int *a, int opt, int mod) {
for (int i = 0; i < n; ++i) if (i < rev[i]) swap(a[i], a[rev[i]]);
for (int i = 1; i < n; i <<= 1) {
int gn = Pow(G, (mod - 1) / (i << 1), mod);
for (int j = 0; j < n; j += (i << 1)) {
int t1, t2, g = 1;
for (int k = 0; k < i; ++k, g = 1LL * g*gn%mod) {
t1 = a[j + k], t2 = 1LL * g*a[j + k + i] % mod;
a[j + k] = (t1 + t2) % mod, a[j + k + i] = (t1 - t2 + mod) % mod;
}
}
}
if (opt == -1){
int ny = Pow(n, mod - 2, mod); reverse(a + 1, a + n);//在FFT里面,我们已经利用x在步骤3中完成了翻转。
for (int i = 0; i < n; ++i) a[i] = 1LL * a[i] * ny%mod;
}
}
int ans[3][N], tmp[N];
ll CRT(ll x, ll y, ll z){
ll A = (mul(1ll * x * mod2%M, Pow(mod2%mod1, mod1 - 2, mod1), M) +
mul(1ll * y * mod1%M, Pow(mod1%mod2, mod2 - 2, mod2), M)) % M;
ll K = ((z - A) % mod3 + mod3) % mod3*Pow(M%mod3, mod3 - 2, mod3) % mod3;
return ((K%mod)*(M%mod) % mod + A%mod) % mod;
}
int BB[3][N];
void work(int n, int *a, int *b){
if (n == 1){
b[0] = CRT(Pow(a[0], mod1 - 2, mod1),
Pow(a[0], mod2 - 2, mod2), Pow(a[0], mod3 - 2, mod3)); return;
}
work(n >> 1, a, b);
int len = 0, x = 1;
while (x < (n << 1)) x <<= 1, ++len;
for (int i = 1; i < x; i++)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (len - 1));
for (int k = 0; k < 3; k++)
for (int i = 0; i < n; i++)
ans[k][i] = b[i], ans[k][i + n] = 0;
for (int k = 0; k < 3; k++){
for (int i = 0; i < n; i++) tmp[i] = a[i], tmp[i + n] = 0;
NTT(x, tmp, 1, m[k]), NTT(x, ans[k], 1, m[k]);
for (int i = 0; i < x; i++)
ans[k][i] = 1ll * tmp[i] * ans[k][i] % m[k];
NTT(x, ans[k], -1, m[k]);
}
for (int i = 0; i < n; i++)
ans[0][i]=ans[1][i]=ans[2][i]=(mod-CRT(ans[0][i],ans[1][i],ans[2][i])) % mod;
ans[0][0] = ans[1][0] = ans[2][0] = (ans[0][0] + 2) % mod;
for (int k = 0; k < 3; k++){
for (int i = 0; i < n; i++) tmp[i] = b[i], tmp[i + n] = 0;
NTT(x, tmp, 1, m[k]), NTT(x, ans[k], 1, m[k]);
for (int i = 0; i < x; i++)
ans[k][i] = 1ll * tmp[i] * ans[k][i] % m[k];
NTT(x, ans[k], -1, m[k]);
}
for (int i = 0; i < n; i++)
b[i] = CRT(ans[0][i], ans[1][i], ans[2][i]);
}
void init(){
f[0] = inv[0] = 1;
for (int i = 1; i < N; i++){
f[i] = 1ll * f[i - 1] * i% mod;
inv[i] = 1ll * inv[i - 1] * Pow(i, mod - 2, mod) % mod;
}
for (int i = 0; i < N - 1; i++) a[i] = inv[i + 1];
int len = 1 << 16; work(len, a, B);
for (int i = 0; i < len; i++) B[i] = 1ll * B[i] * f[i] % mod;
}
int main(){
init(); B[1] =mod-B[1];//B[1]+=1; work中m[] 为分解模数
ll n, k; cin >> n >> k;
ll ans = Pow(k + 1, mod - 2, mod);
ll num = 0;
for (int i = 1; i <= k+1; i++)
num = (num + 1ll*C(k + 1, i)*B[k+1-i]% mod*Pow(n , i, mod) % mod) % mod;
cout << ans*num%mod << endl;
}