首页 > 其他分享 >Codeforces 1406E Deleting Numbers

Codeforces 1406E Deleting Numbers

时间:2024-03-01 16:04:40浏览次数:23  
标签:return int 质数 1406E Codeforces sqrt maxn qry Deleting

考虑询问每个质因子及其次数最后组合得到 \(n\)。

注意到 \(n\) 最多只会有 \(1\) 个 \(> \sqrt{n}\) 的质因子。
于是考虑分成 \(\le \sqrt{n}\) 和 \(> \sqrt{n}\) 来考虑。

对于 \(\le \sqrt{n}\) 的 \(p\)。
考虑先 \(\texttt{B}\ p\),那么还剩下的 \(p\) 的倍数就只有 \(x\) 了。
接下来询问 \(\texttt{A}\ p\),如果为 \(1\) 说明 \(p | x\)。
继续询问 \(\texttt{A}\ p^2\),如果为 \(1\) 说明 \(p^2 | x\)。
以此类推。
这部分不会超过 \(147\) 步。

这部分操作完后,剩下的数就只有 \(1\),\(x\) 和 \(> \sqrt{n}\) 的质数了,\(> \sqrt{n}\) 的质数有 \(9527\) 个。
如果 \(x\) 有 \(\le \sqrt{n}\) 的质数,那么在询问 \(x\) 的 \(> \sqrt{n}\) 的质因子时会得到 \(2\),就可以判出。
否则 \(x\) 如果是 \(> \sqrt{n}\) 的质数,考虑分块。
按 \(\lfloor\sqrt{9527}\rfloor=97\) 为块长分块,一次性把块内的质数都删掉,如果说查询 \(\texttt{A}\ 1\) 得到的值对比上次得到的值的差值与当前块块长不一样,就说明 \(x\) 在这个块内。
因为如果 \(x\) 不在这个块内每个质数都会被删掉减少的值就为块长,只有在块内时会使得一个质数不会被删掉就不同。
那么找到其块后就可以暴力询问块内的每个数了。

最坏情况下查询次数 \(147 + 9527 + 97 + \lceil\frac{9527}{97}\rceil = 9870\) 次。

代码
#include<bits/stdc++.h>
const int maxn = 1e5 + 10;
bool vis[maxn], ud[maxn];
int pr[maxn], m;
int main() {
    int n; std::cin >> n;
    for (int i = 2; i <= n; i++)
        if (! vis[i]) {
            pr[++m] = i;
            for (int j = i; j <= n; j += i) vis[j] = 1;
        }
    auto qry = [&](char c, int x) {std::cout << c << ' ' << x << std::endl;};
    auto get = [&]() {int x; std::cin >> x; return x;};
    int x = 1;
    for (int i = 1; i <= m; i++)
        if (1ll * pr[i] * pr[i] <= n) {
            qry('B', pr[i]), get();
            for (int j = pr[i]; ; j *= pr[i]) {
                qry('A', j);
                if (! get()) break;
                x *= pr[i];
                if (1ll * j * pr[i] > n) break;
            }
        }
    std::vector<int> P;
    qry('A', 1);
    int cnt = get(), B = sqrt(cnt);
    auto solve = [&]() {
        qry('A', 1);
        if (get() != cnt) {
            for (int v : P) {
                qry('A', v);
                if (get() == 1) {
                    x *= v;
                    break;
                }
            }
            return true;
        }
        P.clear();
        return false;
    };
    bool f = 0;
    for (int i = 1; i <= m; i++)
        if (1ll * pr[i] * pr[i] > n) {
            cnt--;
            qry('B', pr[i]);
            if (get() == 2) {
                x *= pr[i];
                f = 1;
                break;
            }
            P.push_back(pr[i]);
            if (P.size() == B)
                if (solve()) {f = 1; break;}
        }
    ! f && (solve(), 1);
    qry('C', x);
    return 0;
}

标签:return,int,质数,1406E,Codeforces,sqrt,maxn,qry,Deleting
From: https://www.cnblogs.com/rizynvu/p/18047264

相关文章

  • Codeforces Round 930 (Div. 2) - sol
    20240301由于笔者实力较弱,所以这只是Div2的题解。四年一次的比赛啊,还是要打。Dashboard-CodeforcesRound930(Div.2)-CodeforcesA.ShufflePartyYouaregivenanarray\(a_1,a_2,\ldots,a_n\).Initially,\(a_i=i\)foreach\(1\lei\len\).Theopera......
  • Codeforces 1446D1 Frequency Problem (Easy Version)
    考虑求出全局的众数\(A\)。那么有一个结论,就是答案区间的众数中绝对有\(A\)。考虑反证法,如果没有\(A\),\(A\)在序列中出现的个数一定\(\ge\)区间内众数的出现个数,所以可以一直往外扩展直到\(A\)出现的个数与区间内非\(A\)众数的个数持平,这样肯定更优。于是可以考虑钦......
  • Codeforces 1446D2 Frequency Problem (Hard Version)
    考虑求出全局的众数\(A\)。那么有一个结论,就是答案区间的众数中绝对有\(A\)。考虑反证法,如果没有\(A\),\(A\)在序列中出现的个数一定\(\ge\)区间内众数的出现个数,所以可以一直往外扩展直到\(A\)出现的个数与区间内非\(A\)众数的个数持平,这样肯定更优。于是可以考虑钦......
  • Codeforces 932D Tree
    首先有个动态加叶子的操作,考虑到树剖需要离线下来预处理,便考虑用倍增来维护。首先要找到\(\gea_u\)的最深的父亲\(v\),便可以先用倍增处理好长度为\(2^i\)的链上的\(\max\)。如果\(\max<a_u\),就往上跳,跳不了就是到点\(v\)了。考虑连边\(v\tou\),这仍然会是一棵树(建......
  • Codeforces 1455E Four Points
    首先确定每个点最后走到的是哪一个点。这部分可以枚举全排列。假设左上角的点为\((x_0,y_0)\),右上角的点为\((x_1,y_1)\),左下角的点为\((x_2,y_2)\),右下角的点为\((x_3,y_3)\)。令最终的点为\((x'_0,y'_0)\),以此类推。那么最终的答案就是\(\sum\limits_{i=0}^3|......
  • Codeforces 451E Devu and Flowers
    首先考虑没有\(f_i\)的限制的时候,此时可以用插板法得到方案数为\(\binom{s+n-1}{n-1}\)。考虑钦定\(f_i\)不合法,那么就相当于先在\(i\)这里选\(f_i+1\),剩下的随意分配,方案数就为\(\binom{s-(f_i+1)+n-1}{n-1}\)。算完过后能发现会算重存在\(>1\)......
  • Codeforces 1830C Hyperregular Bracket Strings
    考虑到区间的限制\([l,r]\)就是要求\([l,r]\)里的字符会在\([l,r]\)里找到匹配。假设还有个区间\([l',r']\)满足\(l\lel'\ler\ler'\),能够发现限制变成了\([l,l'),[l',r],(r,r']\)这\(3\)个区间内的字符能在对应区间内找到匹配。继续,假设\(l\lel'\le......
  • Codeforces 863E Turn Off The TV
    能发现其实就是区间加查询区间最小值。如果最小值\(>1\)则这个区间可以删掉。考虑离散化端点,先把区间表示为\([l_i,r_i)\)的形式,方便离散化端点。这样子离散化出来的端点也是\([x,y)\)的形式。对于区间加查询区间最小值,很容易用线段树维护。时间复杂度\(O(n\logn)......
  • Codeforces Round 929 (Div. 3)
    CodeforcesRound929(Div.3)A-TurtlePuzzle:RearrangeandNegate代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;usingpii=pair<ll,ll>;#definefifirst#definesesecondusingi128=__int128_t;usingpiii=pa......
  • 13 Codeforces Round 886 (Div. 4)G. The Morning Star(简单容斥)
    G.TheMorningStar思路:用map记录x,y,以及y-x、y+x从前往后统计一遍答案即可公式\(ans+=cnt[x]+cnt[y]-2*cnt[x,y]+cnt[y+x]+cnt[y-x]\)\(cnt[x]+cny[y]-2*cnt[x,y]\)是统计坐标轴方向的,-2倍是需要把本身这个点给减去容斥是减一倍,这里还需要把自己给挖掉\(cnt[y+x]+cnt[y......