其他分享
首页 > 其他分享> > CF1406E

CF1406E

作者:互联网

传送门
题意:
\(给你一个集合,其中元素为 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;
}

标签:cnt,int,质数,316,CF1406E,因子,操作
来源: https://www.cnblogs.com/Mr-leng/p/14459437.html