传送门
题意:
\(给你一个集合,其中元素为 1~n 中所有的整数,你可以执行以下操作以得到 x 的值:\)
\(A\) $ a:查询目前集合中为 a 的倍数的数的数量。\( \)B$ $ a:a>1输出 A 操作的结果,并将这些数删去,特殊的,x 不会被删去。\( \)C$ \(a:提交答案,x=a\)
\(操作次数不超过1e4\)
这个题,要找到x,我们不妨用质因数分解的思想来完成
首先我们可以发现\(316<=\sqrt{100000}<=317\),那么我们可以将小于\(316\)的质数一个个先进行\(B\)操作,再进行\(A\)操作,得到\(ans\)的值,然后再将操作完的\(ans\)值做\(A\)操作,如果为\(1\),直接输去,如果不为\(1\),那麽说明还差一个大于\(316\)的质数,我们只要能找到这个质数就行了。
我们可以进行\(B\) \(1\)操作只留下\(ans\),\(1e5\)内质数有$9592 $个,然后扫每次一次操作质数就完成了,但是!这种方法被题目禁了因为没好好读题T了好几发。因此,我们需要另寻他法。
注意到大于\(316\)的因子最多只有一个,对于大于\(316\)的质数,我们对其分块,一个块中质数及其倍数删除后,记录剩余的数字个数,然后进行\(A\) \(1\)操作验证剩余数字的个数,如果两个相等,那麽说明因子不在这个质数块里,如果相等,那麽质因子就在这个指数块里,我们在对这个块里所有的质数进行\(A\)操作,即可获得大于\(316\)的质因子。
为了方便计算剩余的数字个数,我们可以先找到大于\(316\)的因子,再进行小于\(316\)的,这样复杂度为最大\(O(2*\sqrt{9592}+9592)\),
int n;
int p[maxn],cnt;
bitset<maxn>vis;
void pre(int N){
cnt=0;
rep(i,2,N){
if(!vis[i]) p[++cnt]=i;
rep(j,1,cnt){
if(i*p[j]>N) break;
vis[i*p[j]]=1;
if(i%p[j]==0) break;
}
}
}
int ask(char c,int x){
putchar(c);ptc;print(x);pts;
fflush(stdout);
int y;
y=read();
return y;
}
int main(){
#ifndef ONLINE_JUDGE
// freopen("in1.txt","r",stdin);
// freopen("2.out","w",stdout);
#endif
n=read();
pre(n);
int ans=1;
int pos=0;
rep(i,1,cnt) if(p[i]<=sqrt(n)) pos=i;
int B=98;
int sum=n,l,r;
rep(i,1,B){
l=(i-1)*B+1;r=min(i*B,cnt);
rep(j,l,r){
if(j<=pos) continue;
sum-=ask('B',p[j]);
}
int tmp=ask('A',1);
if(tmp!=sum){
rep(j,l,r){
if(j<=pos) continue;
tmp=ask('A',p[j]);
if(tmp) {ans=p[j];break;}
}
break;
}
if(r==cnt) break;
}
rep(i,1,pos){
if(ans*p[i]>n) break;
int x=ask('B',p[i]);
int num=0;
int y=ask('A',p[i]);
if(y!=0){
ans*=p[i];
for(int j=p[i]*p[i];j<=n;j*=p[i]){
if(ask('A',j)) ans*=p[i];
else break;
}
}
}
printf("C %d",ans);
fflush(stdout);
return 0;
}