1. 程式人生 > >codeforces 851D Arpa and a list of numbers

codeforces 851D Arpa and a list of numbers

math 質因數 space 可能 ces 很多 pre mes arpa

目錄

  • 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\)

\(y\)之間的關系來求每個數最優的操作代價。但似乎這個題目還有一個亂搞的做法。。
首先我們肯定想到的是枚舉\(1~1e6\)之內的所有素數,然後\(Check\)的貪心的進行選擇(正解也是給予這個的)。但是這樣的復雜度我們是接受不了的,於是我們就會不由自主地進行亂搞想更加優越的做法。首先我們會發現,無論怎樣,讓這所有的數的\(Gcd\)等於2似乎是個不錯的選擇,因為這樣最劣的情況也只會對\(n\)個元素進行修改,所以我們剛開始的時候先\(Check\)一下2,作為當前最優的答案。然後由於復雜度的原因,我們不能枚舉完所有的素數,那麽怎麽辦?那我們就假裝這個答案一定會是某個質因數,並且這個質因數在原來序列中出現過若幹次,而出現的次數越多,那麽作為最優答案的可能性也越大。這是為什麽呢?我也不知道。。我們基於這個似乎不正確的結論,就可以貪心的進行\(Check\)
了。先對於每一個數進行分解質因數,然後貪心的從出現次數由高到低進行枚舉質因數進行\(Check\),大概\(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