标签:problem 公约数 16px 分析 scanf ble lse == 操作
https://codeforces.com/contest/1305/problem/F
给出$n$个数,最少执行多少次操作可以使得$n$个数最大公约数不为1
每次操作可以给某个数加一或者减一
由于因子为$2$时,最多需要执行$n$次操作
所以在寻找到最优因子的情况下,执行两次操作的数的数量不可能多于$\frac{1}{2}$
那么任意选择数组中的一个数$a[i]$,最优因子是$a[i],a[i]+1,a[i]-1$的因子的概率是$\frac{1}{2}$
那么在数组随机选出$100$个数,最优因子不是他们因子的概率是$\left (\frac{1}{2} \right )^{100}$
注意:rand()返回的是1到32767的随机数,想要产生1到2e5的随机数需要两个rand相乘
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,a,b) for (int i=b;i>=a;i--)
#define pb push_back
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef long long ll;
typedef vector<int> VI;
typedef pair<int,int> PII;
const int maxn=2e5+7;
const int INF=1e9+10;
set<ll>se;
int n;
ll a[maxn];
void add(ll x){
    for(ll i=2;i*i<=x;i++){
        if(x%i==0){
            se.insert(i);
            while(x%i==0)x/=i;
        }
    }
    if(x!=1)se.insert(x);
}
ll cal(ll x){
    ll res=0;
    rep(i,1,n){
        if(a[i]>=x)res+=min(a[i]%x,x-a[i]%x);
        else res+=x-a[i]%x;
        if(res>=n)return n;
    }
//    cout<<x<<" "<<res<<endl;
    return res;
}
int main()
{
    srand((unsigned)time(NULL));
    scanf("%d",&n);
    rep(i,1,n)scanf("%lld",&a[i]);
    rep(i,1,10*n){//随机打乱数组的顺序
        int x=(ll)rand()*rand()%n+1;
        int y=(ll)rand()*rand()%n+1;
        swap(a[x],a[y]);
    }
    rep(i,1,min(100,n)){
        add(a[i]);
        add(a[i]+1);
        if(a[i]-1>=2)add(a[i]-1);
    }
    ll ans=n;
    se.insert(2);
    for(auto i:se){
//        cout<<i<<endl;
        ans=min(ans,cal(i));
    }
    printf("%lld\n",ans);
    return 0;
}
codeforces#1305F. Kuroni and the Punishment(随机算法)
标签:problem 公约数 16px 分析 scanf ble lse == 操作
原文地址:https://www.cnblogs.com/carcar/p/12411843.html