• Solution 「CF 1622F」Quadratic Set


    \(\mathscr{Description}\)

      Link.

      求 \(S\subseteq\{1,2,\dots,n\}\),使得 \(\prod_{i\in S}i\) 是完全平方数,并最大化 \(|S|\)

      \(n\le10^6\)

    \(\mathscr{Solution}\)

      爆搜打出 \(20\) 以内的表,发现 \(|S|\approx n\)。先研究偶数 \(n=2k\)

    \[\begin{aligned} \prod_{i=1}^{2k} i! &= \left( \prod_{i=1}^k i! \right)^2 \prod_{i=1}^k 2i\\ &= \left( \prod_{i=1}^k i! \right)^2 2^k k!. \end{aligned} \]

    那么若 \(2^kk!\) 是完全平方数,有 \(|S|=n\);否则若 \(2^k\) 是完全平方数,有 \(|S|=n-1\),删去 \(k!\) 即可;否则至少有 \(|S|=n-2\),只需要删去 \(2!\)\(k!\)。继而,对于奇数 \(n=2k+1\),答案至少为 \(n-3\)

      所以,我们只需要判断 \(|S|\) 能否取 \(n,n-1,n-2\)。这里有个 trick:异或哈希。对于每个素数 \(p\),独立随机生成 hash 值 \(h(p)\),并定义 \(h(ab)=h(a)\oplus h(b)\),这样就能对每个数建立 hash,若两数 \(x,y\) 的唯一分解中指数奇偶性完全一致,就应有 \(h(x)=h(y)\)。利用这个 trick,求出所有 \(h(i!)\) 后顶多拿 unordered map 判一判就能完成 \(S\) 的取值判断了。复杂度为 \(\mathcal O(n)\)(假定 std::unordered_map\(\mathcal O(1)\) 操作)。

    \(\mathscr{Code}\)

    /*+Rainybunny+*/
    
    #include <bits/stdc++.h>
    
    #define rep(i, l, r) for (int i = l, rep##i = r; i <= rep##i; ++i)
    #define per(i, r, l) for (int i = r, per##i = l; i >= per##i; --i)
    
    typedef unsigned long long ULL;
    
    const int MAXN = 1e6;
    int n, pn, pr[MAXN + 5];
    bool npr[MAXN + 5];
    ULL hnum[MAXN + 5], hfac[MAXN + 5];
    std::unordered_map<ULL, int> buc;
    
    inline void init() {
        std::mt19937_64 emt(time(0) ^ 20120712);
        rep (i, 2, n) {
            if (!npr[i]) hnum[pr[++pn] = i] = emt();
            for (int j = 1, t; j <= pn && (t = i * pr[j]) <= n; ++j) {
                npr[t] = true, hnum[t] = hnum[i] ^ hnum[pr[j]];
                if (!(i % pr[j])) break;
            }
        }
        rep (i, 1, n) hfac[i] = hfac[i - 1] ^ hnum[i];
    }
    
    int main() {
        scanf("%d", &n), init();
    
        ULL h = 0;
        rep (i, 1, n) h ^= hfac[i];
        
        if (!h) {
            printf("%d\n", n);
            rep (i, 1, n) printf("%d%c", i, i < n ? ' ' : '\n');
            return 0;
        }
    
        rep (i, 1, n) if (h == hfac[i]) {
            printf("%d\n", n - 1);
            rep (j, 1, n) if (i != j) printf("%d ", j);
            return putchar('\n'), 0;
        }
    
        rep (i, 1, n) buc[hfac[i]] = i;
        rep (i, 1, n) if (buc.count(h ^ hfac[i])) {
            printf("%d\n", n - 2); int tmp = buc[h ^ hfac[i]];
            rep (j, 1, n) if (j != i && j != tmp) printf("%d ", j);
            return putchar('\n'), 0;
        }
    
        printf("%d\n", n - 3);
        rep (i, 1, n - 1) if (i != 2 && i != n >> 1) printf("%d ", i);
        return putchar('\n'), 0;
    }
    
    
  • 相关阅读:
    Sublime Text 命令大全(积累所得)
    端口号
    帝之意志 看透世间
    Session and Cookie的基础用法
    厌胜术
    微信支付
    微信登录
    navicat常用快捷键与SQL基本使用
    idea Spring项目一直报错,但是点击进去就恢复正常了,解决办法,通过mvn idea:module命令生成iml文件
    解决报错WARNING: IPv4 forwarding is disabled. Networking will not work.
  • 原文地址:https://www.cnblogs.com/rainybunny/p/15807405.html
Copyright © 2020-2023  润新知