HDU

来源:互联网 发布:淘宝怎样绑定手机号 编辑:程序博客网 时间:2024/06/09 14:21

A Simple Stone Game


Problem Description
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(1N100000), indicating the number of piles of stones.

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


The sum of N of all test cases is not exceed 5105.
 

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
251 2 3 4 525 7
 

Sample Output
21
 



题意:给你几堆石子,问你最少要移动多少个石子才能使得所有堆的大小的最大公约数>1


解题思路:最容易想到的,就是枚举所有的可能,但是和有10^10这么大。类似判断一个数是否是素数的思想。我们不用枚举全部,只需枚举到  sqrt(sum)即可。但是这样还是会超时。再想想,只需要枚举sum的所有质因数即可。枚举之后,就是计算最少要多少步了,这里很容易想,贪心的填满最大的余数即可。具体看代码。





#include<iostream>#include<deque>#include<memory.h>#include<stdio.h>#include<map>#include<string.h>#include<algorithm>#include<vector>#include<math.h>#include<stack>#include<queue>#include<set>using namespace std;typedef long long int ll;//素数打表#define M 1000005bool visit[1010000];int prime[1000000];void table(){    memset(visit,true,sizeof(visit));    int num = 0;    for (int i = 2; i <= M; ++i){        if (visit[i] == true){            num++;            prime[num] = i;        }        for (int j = 1; ((j <= num) && (i * prime[j] <= M));  ++j){            visit[i * prime[j]] = false;            if (i % prime[j] == 0) break;         }    }}int a[100005];int b[100005];int main(){    int t;    scanf("%d",&t);    table() ;    while(t--){        int n;        scanf("%d",&n);        ll sum=0;        int maxx=0;        for(int i=1;i<=n;i++){            scanf("%d",&a[i]);            sum+=a[i];            maxx=max(maxx,a[i]);        }                ll ans=sum-maxx;//最大值                //枚举每一个素数        for(int p=1;p<=M;p++){                        if(prime[p]==0)                break;                        //如果不是因子,跳过            if(sum%prime[p])                continue;                        //求余            for(int i=1;i<=n;i++){                b[i]=a[i]%prime[p];            }                        //排序            sort(b+1,b+n+1);                        ll ta=0;//统计答案            int l=1,r=n;            //看平均分完要多少次            while(l<r){                int temp=prime[p]-b[r];                if(b[l]>temp){                    b[l]-=temp;                    ta+=temp;                    r--;                }                else{                    b[r]+=b[l];                    ta+=b[l];                    l++;                }            }            ans=min(ans,ta);//取最小        }        printf("%lld\n",ans);    }        return 0;}









原创粉丝点击