E - Guess the Root 拉格朗日差值法+交互
题意:告诉你存在一个未知项系数最高为10的$f(x)$,你最多可以有50次询问,每次询问给出一个$x'$,系统会返回你$f(x')$的值,你需要猜一个$x''$,使得$f(x'')=0$,所有运算都是取模1e6+3下进行的。
思路:拉格朗日插值法的模板题。yyb聚聚的公式
$p(x)=$\sum\limits_{n}^{i=0}$(-1)n-i*p(i)*x*(x-1)*(x-2)*(x-3)*……*(x-n)/((n-i)! * i! * (x-i))$
所以先暴力询问0-10的所有答案,然后判断11-p的答案是否为0即可。
#include<bits/stdc++.h> #define CLR(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const ll p=1e6+3; ll a[11],f[20],jcinv[20],inv[p+2]; ll qpow(ll a,ll b){ ll res=1; a%=p; while(b){ if(b&1)res=res*a%p; b>>=1; a=a*a%p; } return res; } void init(){ f[0]=1; for(int i=1;i<=13;i++)f[i]=f[i-1]*i%p; jcinv[13]=qpow(f[13],p-2); for(int i=13;i>0;i--){ jcinv[i-1]=jcinv[i]*i%p; } inv[1]=1; for(int i=2;i<=p;i++) { inv[i]=inv[p%i]*(p-p/i)%p; } } int main(){ init(); for(int i=0;i<=10;i++) { printf("? %d\n",i); fflush(stdout); scanf("%lld",&a[i]); if(a[i]==0){ printf("! %d\n",i); fflush(stdout); return 0; } } for(int k=11;k<p;k++) { ll up=1; for(int i=0;i<=10;i++)up=up*(k-i)%p; ll res=0; for(int i=0;i<=10;i++) { ll tep=0; tep=a[i]*up%p*jcinv[10-i]%p*jcinv[i]%p*inv[k-i]%p; res=(res+tep*(i%2==0?1:-1)+p)%p; } if(res==0){ printf("! %d\n",k); fflush(stdout); return 0; } } printf("! -1\n"); fflush(stdout); }
——愿为泰山而不骄
qq850874665~~