codeforces 851D Arpa and a list of numbers
阿新 • • 發佈:2018-09-29
math 質因數 space 可能 ces 很多 pre mes arpa 和\(y\)之間的關系來求每個數最優的操作代價。但似乎這個題目還有一個亂搞的做法。。
首先我們肯定想到的是枚舉\(1~1e6\)之內的所有素數,然後\(Check\)的貪心的進行選擇(正解也是給予這個的)。但是這樣的復雜度我們是接受不了的,於是我們就會不由自主地進行亂搞想更加優越的做法。首先我們會發現,無論怎樣,讓這所有的數的\(Gcd\)等於2似乎是個不錯的選擇,因為這樣最劣的情況也只會對\(n\)個元素進行修改,所以我們剛開始的時候先\(Check\)一下2,作為當前最優的答案。然後由於復雜度的原因,我們不能枚舉完所有的素數,那麽怎麽辦?那我們就假裝這個答案一定會是某個質因數,並且這個質因數在原來序列中出現過若幹次,而出現的次數越多,那麽作為最優答案的可能性也越大。這是為什麽呢?我也不知道。。我們基於這個似乎不正確的結論,就可以貪心的進行\(Check\) 了。先對於每一個數進行分解質因數,然後貪心的從出現次數由高到低進行枚舉質因數進行\(Check\),大概\(Check\)個十多個就行了,這樣我們至少就可以過了很多的數據了。至於為什麽這個亂搞做法是正確的。。信息競賽不需要證明。。只要覺得對就行了。。
目錄
- codeforces 851D Arpa and a list of numbers
- 題意
- 題解
- Code
codeforces 851D Arpa and a list of numbers
題目傳送門
題意
給出\(n\)個數,有兩種操作:
1.將一個數從數列中刪除,代價為\(x\)。
2.將一個數加1,代價為\(y\)。
詢問最少花費多少的代價能夠使數列中所有數的\(Gcd\)不為1。
\((1 \leq n \leq 5 \cdot 10^5 , 1 \leq x,y \leq 10^9 , 1 \leq a_i \leq 10^5)\)
題解
emm...這個題目似乎無論是CF上的題解還是各種網上的題解,都是那種利用\(x\)
首先我們肯定想到的是枚舉\(1~1e6\)之內的所有素數,然後\(Check\)的貪心的進行選擇(正解也是給予這個的)。但是這樣的復雜度我們是接受不了的,於是我們就會
啊啊啊哪個dalao來叉掉我啊,或者幫我證明一下啊。。。(逃
Code
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=5e5+500; vector<int>pri; int n,x,y; ll res=2e18; int a[N]; struct Cnt { int idx,cnt; bool operator < (const Cnt &rhs) const { return cnt>rhs.cnt; } }C[2000005]; void Get(int x) { int c=x; for(int i=2;i*i<=c;i++) { if(c%i==0) C[i].cnt++; while(c%i==0) c/=i; } if(c>1) C[c].cnt++; } void Check(int G) { ll ans=0; for(int i=1;i<=n;i++) { if(a[i]%G==0) continue; if(x<=y) { ans+=1ll*x; } else { int s=a[i]%G; s=G-s; ans+=min(1ll*s*y,1ll*x); } } res=min(res,ans); } int main() { scanf("%d%d%d",&n,&x,&y); int Mx=0; for(int i=1;i<=1000000;i++) C[i].idx=i,C[i].cnt=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); Get(a[i]); } Check(2); sort(C+1,C+1000001); vector<int>tmp; tmp.clear(); for(int i=1;i<=10;i++) { if(C[i].cnt) tmp.push_back(C[i].idx); else break; } for(int i=0;i<(int)tmp.size();i++) { Check(tmp[i]); } printf("%lld\n",res); return 0; }
codeforces 851D Arpa and a list of numbers