题解 CF1155E 【Guess the Root】

题目链接

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;
}
原文地址:https://www.cnblogs.com/colazcy/p/14110842.html