【Codeforces 1155E】Guess the Root
拉格朗日插值
题目大意:
这是一道交互题。给定一个不超过 $10$ 次的多项式 $F(x)$,你可以询问不超过 $50$ 次某个点的点值。求 $x$ 满足 $F(x)=0$。在模 $10^6+3$ 意义下进行。
题解:
我们并不需要知道这个多项式的次数,由于至多 $10$ 次,我们就当它是 $10$ 次多项式。然后求出 $12$ 个点的点值后,就可以拉格朗日插值,得到多项式的各项系数了。
然后由于模数较小,直接代入所有 $x$ 求值即可。
实际上如果插值时点值连续,也可以不得到多项式的各项系数,可以直接做到线性求值。
Code:
#include<iostream>
using namespace std;
const int md=1e6+3;
typedef long long LL;
int a[14],iv[md+1],pre[14],suf[14],fac[14];
inline int lagrange(int x){
int ret=0;
pre[0]=suf[13]=1;
for(int i=1;i<=12;++i)pre[i]=(LL)pre[i-1]*(x-i+md)%md;
for(int i=12;i>=1;--i)suf[i]=(LL)suf[i+1]*(x-i+md)%md;
for(int i=1;i<=12;++i){
int fz=pre[i-1]*(LL)suf[i+1]%md*a[i]%md;
int fm=fac[12-i]*fac[i-1]%md*((i&1)?(md-1LL):1LL)%md;
ret=(ret+(LL)fz*iv[fm])%md;
}
return ret;
}
int main(){
iv[1]=1;
for(int i=2;i<=md;++i)
iv[i]=(md-md/i)*(LL)iv[md%i]%md;
for(int i=*fac=1;i<=12;++i)fac[i]=fac[i-1]*i%md;
for(int i=1;i<=12;++i){
cout<<"? "<<i<<'\n';
cout.flush();
cin>>a[i];
}
for(int x=0;x<md;++x){
int s=lagrange(x);
if(s==0){
cout<<"! "<<x<<endl;
cout.flush();
return 0;
}
}
cout<<"! -1"<<endl;
cout.flush();
return 0;
}