题目
题目描述
交互题。一个未知的多项式
f
(
x
)
=
∑
i
=
0
k
−
1
a
i
x
i
f(x)=\sum_{i=0}^{k-1}a_ix^i
f(x)=∑i=0k−1aixi ,你可以询问
f
(
t
)
m
o
d
p
f(t)\bmod p
f(t)modp ,其中
t
t
t 是给定的,而
p
=
1
0
6
+
3
p=10^6+3
p=106+3 是常数。最多询问
50
50
50 次。
现在求一个 r ( r ≥ 0 ) r(r\ge 0) r(r≥0) 使得 f ( r ) ≡ 0 ( m o d p ) f(r)\equiv 0\pmod p f(r)≡0(modp) 。不存在输出 − 1 -1 −1 。
数据范围与提示
多项式长度
k
≤
11
k\le 11
k≤11 ,系数
a
i
≥
0
a_i\ge 0
ai≥0 且
a
i
a_i
ai 不均为
0
0
0 。所有数字均为整数。
思路
注意到多项式的长度很小,可以任意询问 11 11 11 次,而后进行高斯消元,或者是拉格朗日插值。
其实想到暴力确定多项式是不容易的。我本来是考虑直接求出零点。但事实上,在求出多项式以后, r r r 取遍 [ 0 , p ) [0,p) [0,p) 即可。
代码
#include <cstdio>
#include <iostream>
#include <vector>
#include <set>
using namespace std;
inline int readint(){
int a = 0; char c = getchar(), f = 1;
for(; c<'0'||c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c&&c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
const int Mod = 1000003, MaxN = 12;
int inv[Mod];
int a[MaxN][MaxN];
void Gauss(int n){
for(int i=0,t=0; i<n; ++i){
for(int j=i; j<n; ++j)
if(a[j][i] != 0){
t = j; break;
}
if(a[t][i] == 0){
puts("周湘予是妹儿");
return ;
}
for(int j=i; j<=n; ++j)
swap(a[i][j],a[t][j]);
for(int j=0; j<n; ++j){
if(j == i) continue;
int f = 1ll*a[j][i]*inv[a[i][i]]%Mod;
for(int k=i; k<=n; ++k){
a[j][k] -= 1ll*f*a[i][k]%Mod;
a[j][k] = (a[j][k]+Mod)%Mod;
}
}
}
for(int i=0; i<n; ++i)
a[i][i] = 1ll*a[i][n]*inv[a[i][i]]%Mod;
}
int calc(int x,int n){
int res = 0;
for(int i=0,t=1; i<n; ++i,t=1ll*t*x%Mod)
res = (res+1ll*t*a[i][i])%Mod;
return res;
}
int main(){
inv[1] = 1;
for(int i=2; i<Mod; ++i)
inv[i] = (0ll+Mod-Mod/i)*inv[Mod%i]%Mod;
int n = MaxN-1;
for(int i=0; i<n; ++i){
printf("? %d\n",i);
fflush(stdout);
a[i][n] = readint();
a[i][0] = 1;
for(int j=1; j<n; ++j)
a[i][j] = (1ll*a[i][j-1]*i)%Mod;
}
Gauss(n); int ans = -1;
for(int i=0; i<Mod; ++i)
if(calc(i,n) == 0){
ans = i; break;
}
printf("! %d\n",ans);
return 0;
}