Codechef Guess the Prime!

题目传送门

分析:
两发询问出结果,又要感受人类智慧了
先第一次询问\(2^{15}\),得到答案x,我们知道\(P|2^{30}-x\)
如果\(x=0\),那么\(P=2\),偶质数唯一确定可以结束
否则\(P\)为奇质数,我们知道\(\frac{2^{30}-x+1}{2}\equiv \frac{1}{2}(mod~P)\)

第二次询问\(\frac{2^{30}-x+1}{2}\)得到\(y\),那么\(y\equiv \frac{1}{4}(mod~P)\)
所以\(y\)是模\(P\)意义下4的逆元
\(P\)为奇质数,分类讨论一下:
\(P\equiv 1(mod~4)\),则\(y=\frac{3P+1}{4},P=\frac{4y-1}{3}\)
\(P\equiv 3(mod~4)\),则\(y=\frac{P+1}{4},P=4y-1\)
\(\frac{4y-1}{3}\)\(4y-1\)不可能同时为质数(因为多一个因子3),特判一下出答案
果然人类智慧

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<string>

#define maxn 1000005
#define INF 0x3f3f3f3f

using namespace std;

inline int getint()
{
	int num=0,flag=1;char c;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
	return num*flag;
}

char s[maxn];
inline int ask(int x)
{printf("1 %d\n",x),fflush(stdout);return getint();}
inline void answer(int x)
{printf("2 %d\n",x),fflush(stdout),scanf("%s",s);return;}

int main()
{
	int T=getint();
	while(T--)
	{
		int x=ask(1<<15);
		if(!x){answer(2);continue;}
		x=(1<<30)-x;
		while(!(x&1))x>>=1;
		x=ask((x+1)/2);
		if(x==1||(4ll*x-1)%3)answer(4ll*x-1);
		else answer((4ll*x-1)/3);
	}
}

原文地址:https://www.cnblogs.com/IzayoiDoyo/p/13331551.html