CF1155 E.Guess the Root

题目链接:Click here

题目大意:现在有一个至多11项的多项式(F(x)),你可以询问至多50个(x),黑盒子会告诉你(F(x))的值,你现在要找到一个(x)使得(F(x)=0)

Solution:

考虑拉格朗日插值多项式的式子:

[F(x)=sum_{i=0}^n(prod_{0le jle n,i ot =j}frac{x-x_i}{x_i-x_j})y_i ]

因为至多11项,所以我们询问11次即可得到这个多项式

由于(x<1e6+3),得到多项式后我们暴力枚举(x)计算(F(x))即可

Code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e6+3;
int p[11];
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int qpow(int a,int b){
    int re=1;
    while(b){
        if(b&1) re=(re*1ll*a)%mod;
        b>>=1;a=(a*1ll*a)%mod;
    }return re%mod;
}
int query(int x){
    printf("? %d
",x);fflush(stdout);
    int val=read();return val;
}
void write(int x){
    printf("! %d
",x);fflush(stdout);
    exit(0);
}
signed main(){
    for(int i=0;i<=10;i++){
        p[i]=query(i);
        if(p[i]==0) write(i);
    }
    for(int i=0;i<=10;i++){
        int v=1;
        for(int j=0;j<=10;j++){
            if(i==j) continue;
            v=((i-j+mod)%mod*1ll*v)%mod;
        }
        p[i]=(p[i]*1ll*qpow(v,mod-2))%mod;
    }
    for(int i=11;i<mod;i++){
        int v=0;
        for(int j=0;j<=10;j++){
            int val=1;
            for(int k=0;k<=10;k++){
                if(j==k) continue;
                val=((i-k+mod)%mod*1ll*val)%mod;
            }val=(val*1ll*p[j])%mod;
            v=(v+val)%mod;
        }
        if(!v) write(i);
    }write(-1);
    return 0;
}

原文地址:https://www.cnblogs.com/NLDQY/p/11834135.html