问题描述
[BZOJ5339](https://www.lydsy.com/JudgeOnline/problem.php?id=5339)
题解
打出暴力之后,发现就是 \(F(x)=\sum\limits_{i=1}^{x}{i^{m+1}}\) 的时间复杂度比较高
暴力拉格朗日插值一下就好了
\(\mathrm{Code}\)
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=57;
const int mod=1000000007;
int T;
int n,m,x[maxm];
void Init(void){
scanf("%lld",&T);
}
int fpow(int x,int p){
int res(1);
while(p){
if(p&1) res=res*x%mod;p>>=1;
x=x*x%mod;
}
return res;
}
int X[maxm],Y[maxm];
int doit(int x,int k){
int res(0);
for(int i=1;i<=x;i++) res=(res+fpow(i,k))%mod;
return res;
}
void Preprocess(int k){
for(int i=1;i<=k+2;i++) X[i]=i,Y[i]=doit(X[i],k);
}
int calc(int x,int k){
int res(0);
for(int i=1;i<=k+2;i++){
int cnt(1);
for(int j=1;j<=k+2;j++) if(i!=j) cnt=cnt*(X[i]+mod-X[j])%mod;
cnt=fpow(cnt,mod-2);
for(int j=1;j<=k+2;j++) if(i!=j) cnt=cnt*(x+mod-X[j])%mod;
cnt=cnt*Y[i]%mod;
res=(res+cnt)%mod;
}
return res;
}
void Solve(void){
sort(x+1,x+m+1);
Preprocess(m+1);
int k=m+1,res(0);
for(int i=1;i<=k;i++){
res=(res+calc(n-x[i-1],k))%mod;
// for(int j=1;j<=n-x[i-1];j++){
// res=res+fpow(j,k);res=res%mod;
// }
for(int j=i;j<=m;j++){
res=res-fpow(x[j]-x[i-1],k);
res=res+mod;res%=mod;
}
}
printf("%lld\n",res);
}
void Work(void){
while(T--){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;i++) scanf("%lld",&x[i]);
Solve();
}
}
signed main(){
Init();
Work();
return 0;
}