zoukankan      html  css  js  c++  java
  • F. Kuroni and the Punishment (随机 + 思维)

    题目:传送门

    题意:给你 n 个数,然后你每次操作可以选择任意一个数 a[ i ],让它加 1 或者减 1,问最少需要操作几次,可以使得所有 a[ i ] 的 gcd 大于 1

    2 <= n <= 2e5, 1 <= ai <= 1e12

     

    思路:

    考虑最后的 gcd = 2,那这样的话只要把所有奇数加 1 变成偶数就行了,这样的操作数最多是 n 次,也就是每个 a[ i ] 都操作一次。

    那如果还有更优的答案的话,那至少有 n / 2 个数是操作 1次或者0次的,因为你最多可以有 n / 2 个操作两次的。

    这样的话,你随机的在 n 个 a[ i ] 中选择一个数,那么最终的 gcd 是 a[ i ] 或 a[ i ] - 1 或 a[ i ] + 1 的某个质因子的概率是 1 / 2。

    因为你至少有 n / 2 个数是操作一次或者零次的嘛,那我们随机的选择某个 a[ i ],假设它是操作一次或者零次的那个数。

    这样的话, 假设我们随机选择了 100 个 a[ i ],那它们都不是操作一次或者零次的数的概率是 ( 1 / 2 ) ^ 100,这是一个很小的数。

    #include <bits/stdc++.h>
    #define LL long long
    #define mem(i, j) memset(i, j, sizeof(i))
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k; i >= j; i--)
    #define pb push_back
    #define make make_pair
    #define INF INT_MAX
    #define inf LLONG_MAX
    #define PI acos(-1)
    #define fir first
    #define sec second
    using namespace std;
    
    const int N = 1e6 + 5;
    
    int pre[N], vis[N], tot, n;
    
    LL a[N];
    
    set < LL > Q;
    
    void init() {
        rep(i, 2, N - 5) {
            if(!vis[i]) pre[++tot] = i;
            rep(j, 1, tot) {
                if(i * pre[j] > N - 5) break;
                vis[i * pre[j]] = 1;
                if(i % pre[j] == 0) break;
            }
        }
    }
    
    void add(LL x) {
        for(int i = 1; i <= tot && x > 1 && pre[i] * pre[i] <= x; i++) {
            if(x % pre[i] == 0) {
                Q.insert(pre[i]);
                while(x % pre[i] == 0) {
                    x /= pre[i];
                }
            }
        }
        if(x > 1) Q.insert(x);
    }
    
    LL solve(LL x) {
        LL res = 0;
        rep(i, 1, n) {
            LL add = (a[i] < x ? x - a[i] : min(a[i] % x, x - a[i] % x));
            res = min(1LL * n, res + add);
        }
        return res;
    }
    
    int main() {
        init();
        scanf("%d", &n);
        rep(i, 1, n) scanf("%lld", &a[i]);
        shuffle(a + 1, a + 1 + n, default_random_engine (time(0)));
    
        rep(i, 1, min(100, n)) {
            add(a[i]);
            add(a[i] + 1);
            if(a[i] > 1) add(a[i] - 1);
        }
    
        LL ans = n;
    
        for(LL v : Q) {
            ans = min(ans, solve(v));
        }
        printf("%lld
    ", ans);
        return 0;
    }
    一步一步,永不停息
  • 相关阅读:
    Python进阶08 生成器
    Python进阶07 迭代
    Python进阶06 列表推导
    Python进阶05 函数property
    Python基础14 集合
    支付宝支付和微信消息推送
    Redis
    django之contenttype
    数据分析系列
    IPython
  • 原文地址:https://www.cnblogs.com/Willems/p/12426140.html
Copyright © 2011-2022 走看看