52 质因数分解

H - A Simple Stone Game

After he has learned how to play Nim game, Bob begins to try another stone game which seems much easier.

The game goes like this: one player starts the game with N piles of stones. There is ai stones on the ith pile. On one turn, the player can move exactly one stone from one pile to another pile. After one turn, if there exits a number x(x>1) such that for each pile bi is the multiple of x where bi is the number of stone of the this pile now), the game will stop. Now you need to help Bob to calculate the minimum turns he need to stop this boring game. You can regard that 0

is the multiple of any positive number.

Input

The first line is the number of test cases. For each test case, the first line contains one positive number N(1≤N≤100000)

, indicating the number of piles of stones.

The second line contains N positive number, the ith number ai(1≤ai≤100000) indicating the number of stones of the ith pile.


The sum of N of all test cases is not exceed 5∗105

.

Output

For each test case, output a integer donating the answer as described above. If there exist a satisfied number x

initially, you just need to output 0

. It's guaranteed that there exists at least one solution.

Sample Input

2
5
1 2 3 4 5
2
5 7

Sample Output

2
1

这一道题目的意思就是给了我们n堆石子,我们一次只能移动一个石子,让我们移动最少的步数让所有的石子堆之间gcd不是1,并且规定了,0是任何数字的倍数,假设最初的石子是

         最初 :  a[1],    a[2],    a[3]....................a[n];

        最后   :    b[1],    b[2],    b[3]....................b[n];

并且这里有gcd(b[1],...........b[n])>1;

我们可以这么想因为最后每一堆他们之间不互质的话,那么他们肯定是一个数(base)的倍数,换一句话那么最初的石子的数量和也是这一个数(base)的倍数,那么这个数是谁呢,显然是和的质因子;

这里我们知道了怎么来找这些数字的gcd()>1;但是有出现了一个问题就是怎么来求最小步数,拿第一组样例来说

加和是15 分解质因子 3    5

石子                1               2      3     4       5    

gcd取值3        1(1%3)2       0     1       2  我们凑出3来显然是把小的放到大的上面步数少 1  1   2  2 两个1放2上面;(2步)

gcd取值5        1              2        3     4      0  我们凑出5来,把小的放到打的(1,4),(2,3)一共需要(3步);

所以答案是2

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int Max = 1e6+10;
const ll inf = 1e18;

#define rep(i,s,n) for(ll i=s;i<=n;i++)
#define per(i,n,s) for(ll i=n;i>=s;i--)

ll s[Max],a[Max],b[Max],prime[Max],num=0;
bool visited[Max];

void pri(){
       rep(i,0,Max-5) visited[i]=false;
       rep(i,3,Max-5) if(i%2==0) visited[i]=true;
       rep(i,2,sqrt(Max-5)){
          for(int j=i*2;j<=Max-5;j+=i) visited[j]=true;
       }
       rep(i,2,Max-5) if(!visited[i]) prime[num++]=i;
}
ll num1;
void solve(ll x){
   num1=0;
   rep(i,0,num-1){
       if(x==1) break;
      if(x%prime[i]==0){
        s[num1++]=prime[i];
        while(x%prime[i]==0&&x!=1){
            x/=prime[i];
        }
      }
   }
   if(x!=1) s[num1++]=x;
}
int main(){
    pri();
    int t;
    scanf("%d",&t);
    while(t--){
       ll sum=0,sum1=0,n;
       scanf("%lld",&n);
       rep(i,1,n) {
         scanf("%lld",&a[i]);
         sum+=a[i];
       }
       solve(sum);
       ll min1=inf;
       rep(i,0,num1-1){
         ll base=s[i];
         sum=0;
         int num2=0;
         rep(j,1,n){
           b[num2++]=a[j]%base;
           sum+=(a[j]%base);
         }
         if(sum%base==0){
            sum1=0;
            ll to=sum/base;
            sort(b,b+num2);
            rep(j,0,num2-to-1) sum1+=b[j];
            min1=min(min1,sum1);
         }
       }
       printf("%lld\n",min1);
    }
    return 0;
}



猜你喜欢

转载自blog.csdn.net/qq_39792342/article/details/83374689