【随机】Kuroni and the Punishment(CF1305F)
生活随笔
收集整理的這篇文章主要介紹了
【随机】Kuroni and the Punishment(CF1305F)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
luogu
CF1305F
題目大意
給你n個數,每次操作可以使一個數+1或-1,讓你用最小的操作數使所有數的gcd>1
解題思路
顯然把所有數都修改為偶數可以得到 2|gcd,且步數 ≤n\leq n≤n
對于其它方案,至少有一半的數修改次數小于1(如果不滿足,那其他數大于一半且步數 ≥2\geq 2≥2,所以步數大于n,不如前面的方案)
所以每次隨機一個數進行質因數分解,然后考慮每個質因數作為gcd的最小步數(gcd可能是合數,但是只用滿足有一個質因子就好了)
這樣每一次操作得到正確答案的概率最小是 12\frac{1}{2}21?,如果取 k 個數得到正確答案的概率就是 2k?12k\frac{2^k-1}{2^k}2k2k?1?
code
#include<map> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define N 200210 #define NN 1000010 using namespace std; int n,w,p[NN]; ll x,ans,a[N],prime[NN]; map<ll,int>pp; void work() {for(int i=2;i<=1e6;++i){if(!p[i])prime[++w]=i;for(int j=1;j<=w&&i*prime[j]<=1e6;++j){p[i*prime[j]]=1;if(i%prime[j]==0)break;}}return; } ll get(ll x) {if(pp[x])return ans;pp[x]=1;ll sum=0;for(int i=1;i<=n&&sum<ans;++i)sum+=min((a[i]>=x?a[i]%x:x),x-a[i]%x);return sum; } void solve(ll x) {for(int i=1;i<=w&&prime[i]*prime[i]<=x;++i)if(x%prime[i]==0){ans=min(ans,get(prime[i]));while(x%prime[i]==0)x/=prime[i];}if(x>1)ans=min(ans,get(x));return; } int main() {srand(2018729);scanf("%d",&n);work();for(int i=1;i<=n;++i){scanf("%lld",&a[i]);if(a[i]&1)ans++;}for(int k=1;k<=min(20,n/2)&&ans;++k){x=rand()*rand()%n+1;while(p[x])x=rand()*rand()%n+1;p[x]=1;solve(a[x]);solve(a[x]-1);solve(a[x]+1);}printf("%lld",ans);return 0; }總結
以上是生活随笔為你收集整理的【随机】Kuroni and the Punishment(CF1305F)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 会员等级
- 下一篇: 【线段树】Traffic Jams in