Solution CF1155E Guess the Root
题目大意:有一个次数不超过 (10) 的多项式,你可以询问该多项式在 (x) 处的值,询问次数限制 (50) 次。求该多项式的零点(运算在模 (1e6+3) 意义下进行)
交互、高斯消元
分析:
首先模数与次数都较小,所以求零点我们可以直接暴力,那么我们就要想办法把这个多项式给找出来。
(n + 1) 个点可以确定一个 (n) 次多项式(假设待定系数法搞出来的矩阵是满秩的),所以我们直接随机 (50) 个点,高斯消元然后暴力即可
也可以拉格朗日插值
#include <cstdio>
#include <random>
#include <chrono>
#include <cstdlib>
using namespace std;
constexpr int maxn = 64,mod = 1e6 + 3,qtot = 50;
constexpr inline int add(const int a,const int b){return (a + b) % mod;}
constexpr inline int mul(const int a,const int b){return (1ll * a * b) % mod;}
constexpr inline int sub(const int a,const int b){return (a - b + mod) % mod;}
inline int qpow(int base,int b){
int res = 1;
while(b){
if(b & 1)res = mul(res,base);
base = mul(base,base);
b >>= 1;
}
return res;
}
inline int inv(const int x){return qpow(x,mod - 2);}
inline int calc(const int a,const int b){return mul(a,inv(b));}
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
int ques[maxn],mat[maxn][maxn],a[maxn];
inline int query(const int x){
int res;
printf("? %d
",x);fflush(stdout);
scanf("%d",&res);
return res;
}
int mem[maxn][maxn];
inline void query(){
for(int k = 0;k < qtot;k++){
const int x = ques[k];
mat[k][11] = query(x);
for(int i = 0;i <= 10;i++)mat[k][i] = qpow(x,i);
}
}
inline void gauss(){
const int n = qtot - 1;
const int m = 10;
for(int i = 0;i <= m;i++){
int r = -1;
for(int j = i;j <= n;j++)
if(mat[j][i])r = j;
if(r == -1)exit(-1);
swap(mat[i],mat[r]);
for(int j = i + 1;j <= n;j++){
const int k = calc(mat[j][i],mat[i][i]);
for(int l = i;l <= m + 1;l++)mat[j][l] = sub(mat[j][l],mul(mat[i][l],k));
}
}
for(int i = m;i >= 0;i--){
a[i] = mat[i][m + 1];
for(int l = i + 1;l <= m;l++)a[i] = sub(a[i],mul(mat[i][l],a[l]));
a[i] = calc(a[i],mat[i][i]);
}
}
inline int calc(int x){
int res = 0;
for(int i = 0;i <= 10;i++)res = add(res,mul(a[i],qpow(x,i)));
return res;
}
inline void solve(){
for(int i = 0;i < mod;i++)
if(!calc(i)){
printf("! %d
",i);
return;
}
puts("! -1");
}
int main(){
for(int i = 0;i < qtot;i++)ques[i] = rnd() % mod;
query();
gauss();
solve();
return 0;
}