题干:
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 NN piles of stones. There is aiai stones on the iith 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)x(x>1) such that for each pile bibi is the multiple of xx where bibi 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 00 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)N(1≤N≤100000), indicating the number of piles of stones.
The second line contains NN positive number, the iith number ai(1≤ai≤100000)ai(1≤ai≤100000) indicating the number of stones of the iith pile.
The sum of NN of all test cases is not exceed 5∗1055∗105.
Output
For each test case, output a integer donating the answer as described above. If there exist a satisfied number xx initially, you just need to output 00. 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堆石头,每堆石头有a[i]个,每次你能将一堆石头的一个放到其他堆,当存在一个x使得所有的a[i]%x==0,游戏结束,输出游戏进行的最小次数。(n,a[i]<=1e5)
解题报告:
首先这个x可以进行缩减,如果x的倍数是可以的,那x一定是可以的,也就是说我们只需要考虑x是质数就可以了。
那么1e5个数,每个数的质因子还是特别的多的,其实我们也不需要考虑这么多数字,想想他既然有解,说明他x一定可以整数所有数,所以我们不需要分别看这n个数,只需要看看,这n个数的和就可以了。不难发现这个和<=1e10,所以我们可以先求和,然后对和进行质因子分解(不超过10个),然后枚举这些质因子。
对于接下来的处理,首先对枚举的这个数x取模一下,因为剩下的那些数都是没啥用的,然后可以贪心构造,每次都让小的摞到高的上,这样一定可以保证移动次数最少,其实不难发现不可能存在某一堆中移动>x个石子到另一堆上,因为这样相当于没有省略,所以其中x那一部分可以不用挪动,又因为保证有解,所以一定是可以移动过去的。另一种方法是因为给定了总和,给定了x,我们就知道最终要凑出几个堆来,假设需要凑出k堆,所以我们对%x后的值排个序,可以贪心选取前k大的元素,看还需要凑多少出来即可。(代码实现没有讨论的这么麻烦,但是感觉这题还是需要一个严谨的思维过程的wjhnb)
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define FF first
#define SS second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 1e5 + 5;
bool is[MAX];
ll a[MAX],b[MAX];
int cnt;
ll prime[MAX],ans;
void init() {memset(is,1,sizeof is);is[1]=is[0]=0;for(int i = 2; i<MAX; i++) {if(is[i] == 0) continue;prime[++cnt] = i;for(int j = i+i; j<MAX; j+=i) is[j]=0;}
}
vector<ll> vv;
void fj(ll x) {for(int i = 1; i<=cnt; i++) {if(x % prime[i] == 0) {vv.pb(prime[i]);while(x%prime[i] == 0) x /= prime[i];}}if(x>1) vv.pb(x);
}
int main()
{init();int T,n;cin>>T;while(T--) {scanf("%d",&n);ll sum = 0;vv.clear();ans=1e18;for(int i = 1; i<=n; i++) scanf("%lld",a+i),sum += a[i];fj(sum);for(auto x : vv) {ll tmp = 0,tt=0;for(int i = 1; i<=n; i++) {b[i] = a[i]%x;tt += b[i];}sort(b+1,b+n+1);ll zu = tt/x;for(int i = n; i>=n-zu+1; i--) tmp += x - (b[i]);ans = min(ans,tmp); }printf("%lld\n",ans);}return 0 ;
}