• Codeforces 1305F Kuroni and the Punishment (随机化)


    题目链接

    https://codeforces.com/contest/1305/problem/F

    题解

    真的想不出……然而大家都会
    考虑枚举最终所有数的 (gcd),设为 (g). (g=2)时操作次数不超过 (n), 故答案不超过 (n).
    对于 (g>2), 只有操作次数小于 (n) 时才有贡献。那么考虑每个元素的操作次数,肯定存在至少一个元素的操作次数为 (0), 因此只需要枚举那些至少是输入中一个数的因数的数;又不难发现只需要枚举质数。以上都是铺垫,现在离正解只差一个Key observation.
    观察到绝大部分情况下操作次数都是 (0)(1). 具体来讲,至少有一半的数操作次数都不超过 (1). 于是每次随机选序列中的一个数 (x),检验 (x-1,x,x+1) 的所有质因子即可,设进行 (T) 轮,则正确率至少为 ((1-frac{1}{2^T})).
    时间复杂度 (O(T(sqrt W+n))),其中 (W=max a_i).

    代码

    #include<bits/stdc++.h>
    #define llong long long
    #define mkpr make_pair
    #define riterator reverse_iterator
    using namespace std;
    
    inline int read()
    {
    	int x = 0,f = 1; char ch = getchar();
    	for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    	for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
    	return x*f;
    }
    
    const int N = 2e5;
    const int MX = 1e6;
    bool isp[MX+3]; int pri[MX+3];
    llong a[N+3];
    map<llong,int> done;
    int n,prin; llong ans;
    
    int randw() {return (rand()<<15)|rand();}
    
    void EulerSieve()
    {
    	isp[1] = 1;
    	for(int i=2; i<=MX; i++)
    	{
    		if(!isp[i]) {pri[++prin] = i;}
    		for(int j=1; j<=prin&&i*pri[j]<=MX; j++)
    		{
    			isp[i*pri[j]] = 1;
    			if(i%pri[j]==0) break;
    		}
    	}
    }
    
    void check(llong x)
    {
    	if(done.count(x)) return; done[x] = 1;
    	llong ret = 0ll;
    	for(int i=1; i<=n; i++)
    	{
    		ret += a[i]<x?x-a[i]%x:min(a[i]%x,x-a[i]%x);
    	}
    	ans = min(ans,ret);
    }
    void check1(llong x)
    {
    	for(llong i=2; i*i<=x; i++)
    	{
    		if(isp[i]) continue;
    		if(x%i==0)
    		{
    			check(i);
    			while(x%i==0) {x/=i;}
    		}
    	}
    	if(x>1) {check(x);}
    }
    
    int main()
    {
    	srand(time(NULL));
    	EulerSieve();
    	scanf("%d",&n);
    	for(int i=1; i<=n; i++) scanf("%lld",&a[i]);
    	for(int i=1; i<=n; i++) {ans += a[i]&1;}
    	for(int T=1; T<=20; T++)
    	{
    		int i = randw()%n+1;
    		check1(a[i]); check1(a[i]-1); check1(a[i]+1);
    	}
    	printf("%I64d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    异常总结201304
    Android开发资料[20121125]
    大素数的生成
    django 获取用户IP地址
    python包管理工具pip
    mysql大表修改结构
    素数的检测
    一致性哈希算法 python实现
    素数的生成筛选法
    相似哈希simhash
  • 原文地址:https://www.cnblogs.com/suncongbo/p/12555523.html
Copyright © 2020-2023  润新知