Codeforces 1305F. Kuroni and the Punishment 题解

题目链接:F. Kuroni and the Punishment

题目大意:给定一个正整数序列\(a_1,a_2,\cdots,a_n\),你每一次操作可以使每一个数\(+1\)\(-1\),但必须保证操作后的数仍为正整数,问最少用多少次操作才能使它们的最大公约数不为\(1\)


题解:这样的题拿到之后第一反应就是瞎搞(然而博主太菜了赛时瞎搞了16发都没对),肯定是枚举素因子然后计算答案了,我们先假设我们已经知道了素因子是什么,假设其为\(p\),所以有一个很明显的贪心策略,就是每一个数只会变成与它相邻的两个是\(p\)的倍数的正整数,所以我们就可以得到一个\(O(n)\)的贪心策略。先把\(2\)\(3\)跑一遍(因为这两个最容易成为答案),然后就是随机了,随机抽取序列中的一个数,令其为\(x\),然后把\(x\)分解质因数,对它的每一个质因数都跑一遍,然后再这么操作\(x-1\)\(x+1\),这样的话算法错误的概率是\(\frac{1}{2}\),然后重新随机。这样随机 20 次之后,程序错误的概率就是\(2^{-20}\),当然了,赛场上没有必要这么算,直接卡时间就可以了。

下面是代码(随机函数最好用 mt19937 ,可能是博主太菜了用 rand 结果WA7):

#include <ctime>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
template<typename Elem>
void read(Elem &a){
	a=0;
	char c=getchar();
	while(c<'0'||c>'9'){
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		a=(a<<1)+(a<<3)+(c^48);
		c=getchar();
	}
}
const int Maxn=200000;
typedef long long ll;
int n;
ll a[Maxn+5];
ll p[Maxn+5];
int p_len;
void div(ll x){
	p_len=0;
	for(ll i=2;i*i<=x;i++){
		if(x%i==0){
			p[++p_len]=i;
			while(x%i==0){
				x/=i;
			}
		}
	}
	if(x>1){
		p[++p_len]=x;
	}
}
ll work(ll p){
	ll ans=0;
	for(int i=1;i<=n;i++){
		if(a[i]<p){
			ans+=p-a[i];
			if(ans>=n){
				break;
			}
			continue;
		}
		ll fron=a[i]/p;
		ll bac=(fron+1)*p;
		fron*=p;
		ans+=min(a[i]-fron,bac-a[i]);
		if(ans>=n){
			break;
		}
	}
	return ans;
}
int main(){
	clock_t begin,end;
	begin=clock();
	mt19937 rnd(time(NULL));
	read(n);
	for(int i=1;i<=n;i++){
		read(a[i]);
	}
	ll ans=n;
	ll num=0;
	for(int i=1;i<=n;i++){
		if(a[i]&1){
			num++;
		}
	}
	ans=min(ans,num);
	num=0;
	for(int i=1;i<=n;i++){
		if(a[i]==1){
			num+=2;
		}
		else if(a[i]%3!=0){
			num++;
		}
	}
	ans=min(ans,num);
	while(1){
		int x=rnd()%n+1;
		div(a[x]);
		for(int i=1;i<=p_len;i++){
			ans=min(ans,work(p[i]));
		}
		div(a[x]-1);
		for(int i=1;i<=p_len;i++){
			ans=min(ans,work(p[i]));
		}
		div(a[x]+1);
		for(int i=1;i<=p_len;i++){
			ans=min(ans,work(p[i]));
		}
		end=clock();
		if((end-begin)*1.0/CLOCKS_PER_SEC>2.0){
			break;
		}
	}
	cout<<ans<<endl;
	return 0;
}
posted @ 2020-03-04 09:41  with_hope  阅读(487)  评论(3编辑  收藏  举报