题解CF1406E Deleting Numbers

CF1406E Deleting Numbers

交互题

考虑枚举所有n以内的质数,用一次查询B,再进行查询A,若返回1,则说明a为当前枚举的质数的倍数

考虑到唯一分解定理,再不断枚举当前质数的幂次方,进行查询A,最终可以确定a.

很明显,这样的操作次数是质因子数+幂次方数的,而100000内的质数有9600多个,所以会超出题目的限制

可以按两种情况考虑

1.\(x\le\sqrt{n}\) 直接暴力枚举

2.\(x>\sqrt{n}\),这时假设已经枚举完了所有的小质数,得到的答案为ans

A:ans>1,这时集合内就只剩大于 \(\sqrt{n}\) 的质数了,所以直接对每一个质数*ans进行查询A,若返回1,则为答案

B:ans=1,说明答案为一个质数,但不可能直接枚举每一个质数,所以可以对每一个质数进行分块处理,分成 \(\sqrt{n}\) 块,首先

对每一块中的所有数进行一次查询B,再对1进行一次查询A,比较是否有减少的数,若有,就直接在块中暴力查询即可

代码

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int N = 1e5 + 5;
typedef long long ll;

bool st[N];
int prime[N], tot;

void init(int n)
{
    for (int i = 2; i <= n; i++)
    {
        if (!st[i])
            prime[++tot] = i;
        for (int j = 1; i * prime[j] <= n; j++)
        {
            st[i * prime[j]] = true;
            if (i % prime[j] == 0)
                break;
        }
    }
}

int ask_A(int x)
{
    printf("A %d\n", x);
    fflush(stdout);scanf("%d", &x);
    return x;
}

int ask_B(int x)
{
    printf("B %d\n", x);
    fflush(stdout);scanf("%d", &x);
    return x;
}

int main()
{ 
    int n, x, ans = 1, t = 0;
    scanf("%d", &n);
    init(n);
    int sn = sqrt(n);
    for (int i = 1; prime[i] <= sn && i <= tot; i++)
    { 
        x = ask_B(prime[i]);
        if (!x) continue;
        int p = prime[i];
        if (!ask_A(p))
            continue;
        while (p * prime[i] <= n && ask_A(p * prime[i]))
            p *= prime[i];
        ans *= p;
        t = i;
    }
    if (ans > 1)
    {
        for (int i = t + 1; (ll)prime[i] * ans <= n; i++)
        {
            if (ask_A(ans * prime[i]))
            {
                printf("C %d\n", ans * prime[i]);
                fflush(stdout);
                return 0;
            }
        }
    }
    else
    {
        int len = sqrt(tot);
        for (int l = t + 1; l <= tot; l += len)
        {
            int r = min(tot, l + len - 1);
            for (int i = l; i <= r; i++)
                ask_B(prime[i]);
            x = ask_A(1);
            if (x > tot - r + 1)
            {
                for (int i = l; i <= r; i++)
                {
                    if (ask_A(prime[i]))
                    {
                        printf("C %d", prime[i]);
                        fflush(stdout);
                        return 0;
                    }  
                }
            }
        }
    }
    printf("C %d\n", ans);
    fflush(stdout);
    return 0;
}
posted @ 2021-04-27 20:32  DSHUAIB  阅读(39)  评论(0编辑  收藏  举报