个点可以确定一个 次多项式。拉格朗日插值可以实现,对于某个 次多项式函数 ,如果我们已知了这 个点,就可以 的时间复杂度求出
具体来说,我们我们知道了多项式函数上的 个点 ,然后有公式:
如果 是连续的,比如 ,那么我们可以通过预处理, 的时间复杂度求出
首先预处理出阶乘 以及阶乘逆元,然后对于要求出的点 ,预处理出下面两值:
然后有公式:
https://codeforces.com/problemset/problem/622/F
题目描述
求
数据范围
,
笔记
次方求和,求和公式是 次的,我们先暴力算出 个点,然后插值即可
cpp1234567891011121314151617181920212223242526272829303132#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define ls(k) (k)<<1
#define rs(k) (k)<<1|1
#define debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
const int inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
typedef pair<int,int> pii;
#define _ 2000006
int fac[_],inv[_],pre[_],suf[_],y[_];
inline int qpow(int a,int p,int res=1){for(;p;p>>=1,a=a*a%mod)if(p&1)res=res*a%mod;return res;}
inline void subtask(){
fac[0]=1;
for(int i=1;i<=2000000;i++) fac[i]=fac[i-1]*i%mod;
int n,k;cin>>n>>k;
for(int i=1;i<=k+2;i++) y[i]=(y[i-1]+qpow(i,k))%mod;
pre[0]=1;
for(int i=1;i<=k+2;i++) pre[i]=pre[i-1]*(n-i)%mod;
suf[k+3]=1;
for(int i=k+2;i>=1;i--) suf[i]=suf[i+1]*(n-i)%mod;
int ans=0;
for(int i=1;i<=k+2;i++) ans+=((k+2-i)%2==0?1:-1)*y[i]*pre[i-1]%mod*suf[i+1]%mod*qpow(fac[i-1],mod-2)%mod*qpow(fac[k+2-i],mod-2)%mod,ans%=mod;
cout<<(ans+mod)%mod;
}
signed main(){
ios::sync_with_stdio(false);
int t=1;//cin>>t;
while(t--) subtask();
return 0;
}
https://www.luogu.com.cn/problem/P4593
题目描述
现在有 ,共 个数字,然后去掉其中 个数字。然后每次操作,都可以让所有的数字减一,如果减完之后有数字变为 ,则去掉该数字,然后再把所有的数字减一,由数字归零引发的减一也算在这次操作中。我们设 为需要多少次操作才能把所有的数字归零。每次操作,对于每个数字,都会产生 的分数,其中 为减一之前的数字。
求出把所有数字归零后,获得的总分数。多组测试数据
数据范围
笔记
首先需要看出 ,手推几个样例然后感性理解一下就能得出来了
去掉数字后,会把 分成若干数字连续的段
然后我们把贡献拆开,对于一个数字,考虑他会对总分数产生什么样的贡献。设被去掉的数字为 ,然后设 令 ,我们发现数字 对答案的贡献为 ,其中只计算小于 的 。手推几个样例然后感性理解一下就能得出来了
我们又发现,如果 固定, 在某个区间上连续变化的话, 也是连续变化的, 就可以像上道题那样求出
于是答案变为了
cpp123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define ls(k) (k)<<1
#define rs(k) (k)<<1|1
#define debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
const int inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
typedef pair<int,int> pii;
int fac[66],inv[66],y[66],n,m,pre[66],suf[66];
inline int qpow(int a,int p,int res=1){for(;p;p>>=1,a=a*a%mod)if(p&1)res=res*a%mod;return res;}
inline void subtask(){
cin>>n>>m;
vector<int> ve;
for(int i=1,x;i<=m;i++) cin>>x,ve.push_back(x);
ve.push_back(0);sort(ve.begin(),ve.end());
int end=n;
for(int i=ve.size()-1;i>=0;i--) if(ve[i]==end) m--,end--,n--;
int k=m+1;
for(int i=1;i<=k+2;i++) y[i]=(y[i-1]+qpow(i,k))%mod;
auto f=[k](int x){
if(x==0) return (long long)0;
pre[0]=1;
for(int i=1;i<=k+2;i++) pre[i]=pre[i-1]*(x-i)%mod;
suf[k+3]=1;
for(int i=k+2;i>=1;i--) suf[i]=suf[i+1]*(x-i)%mod;
int res=0;
for(int i=1;i<=k+2;i++) res+=((k+2-i)%2==0?1:-1)*y[i]*pre[i-1]%mod*suf[i+1]%mod*inv[i-1]%mod*inv[k+2-i]%mod,res%=mod;
return (res+mod)%mod;
};
auto flr=[f](int l,int r){return (f(r)-f(l-1)+mod)%mod;};
vector<pii> ran;
int l=1;
for(auto x:ve){
if(!x) continue;
if(x==l) l++;
else{
ran.push_back(pii(l,x-1));
l=x+1;
}
}
if(l<=n) ran.push_back(pii(l,n));
int res=0;
for(auto to:ran){
for(auto x:ve){
if(x>to.first) break;
res+=flr(to.first-x,to.second-x);res%=mod;
}
}
cout<<res<<endl;
}
signed main(){
fac[0]=1;
for(int i=1;i<=60;i++) fac[i]=fac[i-1]*i%mod;
inv[60]=qpow(fac[60],mod-2);
for(int i=60-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
ios::sync_with_stdio(false);
int t;cin>>t;
while(t--) subtask();
return 0;
}