zoukankan      html  css  js  c++  java
  • CF1406E Deleting Numbers

    本来是本着口胡一下的原则去想的,但是最后又调了一个晚上

    首先我们有一个很naive的想法,可以枚举每一个质数(p),先删去它的倍数然后在问是否有(p)的倍数,就可以用两次操作判断出(p)是否为(x)的倍数了

    然后我们粗略一算,(10^5)以内的质数有九千多个,直接GG了

    但是我们发现这个想法很好,因为涉及到质数的情况很容易按(sqrt n)分开来讨论

    因此我们考虑先把(sqrt n)内的(x)的约数序列(d_{1cdots m})求出来,然后从(cur=prod_{i=1}^m d_i)开始扩展答案

    每次尝试不断地给(cur)乘上(d_i),然后判断是否仍为(x)的约数即可

    由于每个(d_i)更新(cur)最多只有$log $级别的次数,因此可以保证操作次数

    但是我们发现此时(x)可能还有一个约数是大于(sqrt n)的质数,容易发现当我们删除完所有的小质数的倍数后,剩下的数恰好是所有的大质数(或者包含(x)

    因此我们可以去枚举所有大质数(p),判断(A(p))是否等于(2)即可(即剩下了(p)(p imes cur)),答案就是(p imes cur)

    所以接下来我们就要讨论答案就是一个大质数的情况了,由于大质数很多,如果我们还是对于每个数都花上(2)次操作去询问那么显然还是GG了

    于是陈指导提出了奇妙的阈值做法,具体地,我们设(S)表示删去连续的(S)个数之后来检验一次答案是否在这(S)个数之中

    若在的话我们只需要在这(S)个数之件扫一遍进行询问就可以得出答案了

    所以我们要最小化(S+frac{num}{S})(num)表示剩下的大质数数量),取(S=sqrt {num})即可,此时询问次数(num+2sqrt {num})

    实测可以完美的卡着上限通过此题

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #define RI register int
    #define CI const int&
    #define A(x) (printf("A %d
    ",x),fflush(stdout),scanf("%d",&res),res)
    #define B(x) (printf("B %d
    ",x),fflush(stdout),scanf("%d",&res),res)
    #define C(x) (printf("C %d
    ",x),fflush(stdout))
    using namespace std;
    const int N=100005;
    int n,p[N],t[N],tot,res,cnt,cur,ct,S; bool vis[N];
    inline void init(CI n)
    {
    	RI i,j; for (i=2;i<=n;++i)
    	{
    		if (!vis[i]) p[++cnt]=i;
    		for (j=1;j<=cnt&&i*p[j]<=n;++j)
    		{
    			vis[i*p[j]]=1; if (i%p[j]==0) break;
    		}
    	}
    }
    inline int find(CI l,CI r)
    {
    	for (RI i=l;i<=r;++i) if (A(p[i])) return p[i];
    }
    int main()
    {
    	RI i; for (scanf("%d",&n),init(n),i=1;i<=cnt&&p[i]*p[i]<=n;++i)
    	if (B(p[i]),A(p[i])) t[++tot]=p[i]; int tp=i; if (tot)
    	{
    		for (cur=i=1;i<=tot;++i) cur*=t[i];
    		for (i=1;i<=tot;++i) while (cur*t[i]<=n&&A(cur*t[i])) cur*=t[i];
    		for (i=tp;i<=cnt;++i) if (A(p[i])==2) return C(cur*p[i]),0;
    		return C(cur),0;
    	}
    	for (cur=cnt-i+2,S=sqrt(cur);i<=cnt;++i)
    	if (B(p[i]),--cur,++ct==S) { if (A(1)!=cur) return C(find(i-S+1,i)),0; ct=0; }
    	return C(A(1)!=1?find(cnt-ct+1,cnt):1),0;
    }
    
  • 相关阅读:
    [Abp vNext 入坑分享]
    [Abp vNext 入坑分享]
    [Abp vNext 入坑分享]
    [Abp vNext 入坑分享]
    [Abp vNext 入坑分享]
    [Abp vNext 入坑分享]
    [Abp vNext 入坑分享]
    [Abp vNext 入坑分享]
    腾讯云集群服务部署mysql并挂载到服务器
    加密解密五种算法的实现
  • 原文地址:https://www.cnblogs.com/cjjsb/p/13687858.html
Copyright © 2011-2022 走看看