题目大意
交互题
有一个[1,n]中的数x,要求在10000次操作内找出,有一个集合{1...n}和三种操作
A:询问集合内a的倍数个数
B:询问集合内a(a>=2)的倍数个数,同时删掉除x外所有a的倍数
C:回答
题解
在被Good Bye2019打出心里阴影后九个月没打了尝试上分
由于10000>=9592(质数个数)+171(<=√n的质数的最大指数和)+100(√9592)*2,所以做法一目了然
简单的思路:删掉所有质数,之后依次确定每个质数的指数
这样次数至少是个数*2,但是由于>√n的质数只有最多一个,所以可以先求出这个质数,把>√n的每100个分块,删完之后再查询a=1,这样可以用200次额外操作解决
<=√n的全部删掉后依次确定即可
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
//#define file
using namespace std;
int p[100001],n,s,i,j,k,l,len,sum,ls,S,s2,ans;
bool f[100001];
void init()
{
fo(i,2,n)
{
if (!f[i]) p[++len]=i;
fo(j,1,len)
if (1ll*i*p[j]<=n)
{
f[i*p[j]]=1;
if (!(i%p[j])) break;
}
else break;
}
}
void ask(char ch,int s) {printf("%c %d\n",ch,s);fflush(stdout);}
void del(int t) {sum-=f[t];f[t]=0;}
void find()
{
fo(l,1,len)
if (p[l]>s) break;
S=1;
k=0;
ls=l-1;
fo(i,l,len)
{
++k;
ask('B',p[i]);
scanf("%d",&s2);
for (j=p[i]; j<=n; j+=p[i]) del(j);
if (k==100 || i==len)
{
ask('A',1);
scanf("%d",&s2);
if (s2!=sum)
{
fo(j,ls+1,i)
{
ask('A',p[j]);
scanf("%d",&s2);
if (s2==1) {S=p[j];return;}
}
}
k=0,ls=i;
}
}
}
int main()
{
scanf("%d",&n);s=floor(sqrt(n));
init();
fo(i,1,n) f[i]=1;sum=n;
find();
fo(i,1,len)
if (f[p[i]])
{
ask('B',p[i]);
scanf("%d",&s2);
for (j=p[i]; j<=n; j+=p[i]) del(j);
}
ans=S;
fo(i,1,len)
if (p[i]<=s)
{
j=p[i],k=1;
while (j<=n)
{
ask('A',j);
scanf("%d",&s2);
if (s2) ans*=p[i];
else break;
if (j<=n/p[i]) j*=p[i];
else break;
}
}
ask('C',ans);
fclose(stdin);
fclose(stdout);
return 0;
}