CF1665D 题解

· · 题解

思路:

首先,我们需要找到一些正整数,使它们满足:

1.乘积在10^92\times10^9之间;

2.两两互质。

例如 \{ 2,11,13,17,19,23,29,31 \} 就是一组满足条件的正整数。

设这些正整数的乘积为X,最大的正整数为Y,要猜的数为n.

然后,提出 Y-1 次询问,第 i 次询问中 A=i,B=X+i.

通过这些询问,我们可以知道 n+1,n+2,…n+Y-1分别是哪些正整数的倍数,从而可以推出 n 对这些正整数取模的结果。

例如,我们通过询问得到了 gcd(n+v,n+X+v) 是11的倍数,那么就有 n \equiv -v \left(mod \; 11\right)

利用中国剩余定理解同余方程,即可解出 $n$ 的值。 关于正整数,一种比较优秀的选法是:$\{ 16,9,7,11,13,17,19,23 \}$,可以做到22次询问出结果。 ## 代码: ```cpp #include<bits/stdc++.h> using namespace std; const long long NUM=1070845776; //NUM是下面几个数的乘积 const int P[10]={16,9,7,11,13,17,19,23}; int N; long long M,A[11],m[11],t[11],Ans; void exgcd(long long a,long long b,long long &x,long long &y){ if(b==0){ x=1; y=0; }else{ exgcd(b,a%b,x,y); long long t=x; x=y; y=t-(a/b)*y; } } long long inv(long long a,long long p){ a%=p; long long x,y; exgcd(a,p,x,y); return x>=0?x%p:x%p+p; } long long CRT(){ //中国剩余定理解同余方程 N=8,M=NUM; Ans=0; for(int i=0;i<N;i++){ m[i]=M/P[i]; t[i]=inv(m[i],P[i]); Ans=(((m[i]*t[i]%M)*A[i])%M+Ans)%M; } return Ans; } int T,n,cnt; long long res; void solve(){ for(int i=0;i<8;i++){ A[i]=0; //A[i]初始化为0,后面询问没有赋值就说明n自己就是这个数的倍数 } for(int i=1;i<=22;i++){ printf("? %d %lld\n",i,NUM+i); fflush(stdout); scanf("%lld",&res); for(int j=0;j<8;j++){ if(res%P[j]==0){ A[j]=(P[j]-(i%P[j]))%P[j]; } } } printf("! %lld\n",CRT()); return; } int main(){ scanf("%d",&T); while(T--){ solve(); fflush(stdout); } return 0; } ```