您的位置:首页 > 其它

[BZOJ2655] calc - 拉格朗日插值,dp

2017-04-17 12:10 375 查看
考虑直接选择n个不相同的数 可以轻易设计一个dp

f[i][j] = f[i-1][j] + i f[i-1][j-1]

用归纳法可以证明 F(i,j)是一个关于i的2j次多项式
可以通过得到i=1...2n+1的值来插出答案暴力dp时间复杂度O(n^2)


暴力插出多项式的时间复杂度是O(n^3)但我们只要单点求值 套用拉格朗日插值即可 时间复杂度O(n) 但是这里由于前面是O(n^2)完全可以O(n^2)来暴力计算下面这个式子。 






总时间复杂度O(n^2)



整天写这种<1K的题还有什么前途…

#include"bits/stdc++.h"
using namespace std;
const int N=505;
typedef long long LL;
int f[2*N]
,x,n,P,ans,m;
int inv(int a,int t=P-2){
int r=1;
while(t){
if(t&1)r=(LL)r*a%P;
a=(LL)a*a%P;t>>=1;
}
return r;
}
int main(){
cin>>x>>n>>P;
f[0][0]=1;m=2*n+1;
for(int i=1;i<=m;i++)for(int j=f[i][0]=1;j<=n;j++)f[i][j]=(f[i-1][j]+(LL)i*f[i-1][j-1])%P;
for(int i=1;i<=m;i++){
int a=f[i]
,b=1;
for(int j=1;j<=m;j++)if(i!=j)a=(LL)a*(x-j)%P,b=(LL)b*(i-j)%P;
a=(LL)a*inv(b)%P;
ans=(ans+a)%P;
}
for(int i=1;i<=n;i++)ans=(LL)ans*i%P;
cout<<(ans+P)%P;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: