傳送門
文章目錄
題意:
給你nnn個(gè)數(shù),每次操作可以選擇將某個(gè)數(shù)+1,?1+1,-1+1,?1,求最少進(jìn)行多少次操作使得所有數(shù)都為正數(shù)且gcd>1gcd>1gcd>1。
思路:
考慮gcd=2gcd=2gcd=2的情況,即將所有數(shù)變成偶數(shù),這樣的操作最多有nnn次。
再考慮證明一個(gè)結(jié)論:操作數(shù)量≥2\ge2≥2的數(shù)不超過(guò)n2\frac{n}{2}2n?。
利用反證法,如果超過(guò)n2\frac{n}{2}2n?,那么總的操作數(shù)>n2?2=n>\frac{n}{2}*2=n>2n??2=n,與上面結(jié)論不符合,不成立。
所以對(duì)于一個(gè)數(shù),這個(gè)數(shù)至少有12\frac{1}{2}21?的概率被最多操作一次,那么一個(gè)隨機(jī)算法就來(lái)啦,從序列中隨機(jī)選出來(lái)kkk個(gè)數(shù),將ai,ai+1,ai?1a_i,a_i+1,a_i-1ai?,ai?+1,ai??1分解質(zhì)因子,對(duì)于每個(gè)因子計(jì)算答案,正確率為1?12k1-\frac{1}{2^k}1?2k1?,kkk足夠大的時(shí)候很難出錯(cuò),可是我臉黑雅痞,k=50k=50k=50都能wawawa,試了各種,不是TTT就是wawawa的,不得不說(shuō)臉是真滴黑,randomshufflerandom\ \ shufflerandom??shuffle三遍才過(guò)。
update:update:update: 知道為什么TTT了,我存質(zhì)因子用的vectorvectorvector,最后還需要排序去重,改成mapmapmap就快多了。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=1000010,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
;
map
<LL
,int>diver
;
LL a
[N
];
LL prime
[N
],cnt
;
bool st
[N
];void get_prime(int n
) {for(int i
=2;i
<=n
;i
++) {if(!st
[i
]) {prime
[++cnt
]=i
;for(int j
=i
+i
;j
<=n
;j
+=i
) st
[j
]=1;}}
}void divide(LL x
) {for(int i
=1;i
<=cnt
&&prime
[i
]<=x
;i
++) {if(x
%prime
[i
]==0) {diver
[prime
[i
]]=1;while(x
%prime
[i
]==0) x
/=prime
[i
];}}if(x
>1) diver
[x
]=1;
}LL
calc(LL x
) {LL now
=0;for(int i
=1;i
<=n
;i
++) {if(x
>a
[i
]) now
+=x
-a
[i
];else now
+=min(a
[i
]%x
,x
-a
[i
]%x
);}return now
;
}int main()
{
get_prime(1e6);scanf("%d",&n
);for(int i
=1;i
<=n
;i
++) scanf("%lld",&a
[i
]);random_shuffle(a
+1,a
+1+n
);random_shuffle(a
+1,a
+1+n
);random_shuffle(a
+1,a
+1+n
);for(int i
=1;i
<=min(100,n
);i
++) {divide(a
[i
]);divide(a
[i
]+1);divide(a
[i
]-1);}LL ans
=n
;for(auto x
:diver
) ans
=min(ans
,calc(x
.first
));printf("%lld\n",ans
);return 0;
}
總結(jié)
以上是生活随笔為你收集整理的Ozon Tech Challenge 2020 (Div.1 + Div.2) F. Kuroni and the Punishment 随机化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。