2017ccpc哈尔滨区域赛H

n堆石子 每次只能拿一个石子从一堆移到另一堆  知道所有的堆的石子数目都能整除x(x>1) 问最小移动次数 

枚举x的可能取值  即a[i]和的素因子即可  合因子的区间变化会比较大   然后求余 每次都把石子移到余数最大的那一堆,加起来的总和求最小值。

注意 开longlong

 1 #include <stdio.h>
 2 #include <math.h>
 3 #include <string.h>
 4 #include <stdlib.h>
 5 #include <iostream>
 6 #include <sstream>
 7 #include <algorithm>
 8 #include <string>
 9 #include <queue>
10 #include <ctime>
11 #include <vector>
12 using namespace std;
13 const int maxn= 1e5+5;
14 const int maxm= 1e6+5;
15 const int inf = 0x3f3f3f3f;
16 typedef long long ll;
17 ll su[maxm];
18 int a[maxn],b[maxn];
19 int cnt,n;
20 void sushu(ll x)
21 {
22     cnt=0;
23     for(int i=2;i<=sqrt(x);i++)
24     {
25         if(x%i==0)
26             su[cnt++]=i;
27         while(x%i==0)
28             x/=i;
29     }
30     su[cnt++]=x;
31 }
32 int cmp(int a,int b)
33 {
34     return a>b;
35 }
36 int main()
37 {
38     int t;
39     scanf("%d",&t);
40     while(t--)
41     {
42         scanf("%d",&n);
43         ll sum=0;
44         for(int i=0;i<n;i++)
45         {
46             scanf("%d",&a[i]);
47             sum+=a[i];
48         }
49         sushu(sum);
50         ll maxx=99999999999;
51         for(int i=0;i<cnt;i++)
52         {
53             ll sum=0,cont=0;
54             for(int j=0;j<n;j++)
55             {
56                 b[j]=a[j]%su[i];
57                 sum+=b[j];
58             }
59             sort(b,b+n,cmp);
60             int k=0;
61             while(sum!=0&&k<n)
62             {
63                 cont+=su[i]-b[k++];
64                 sum-=su[i];
65             }
66             maxx=min(maxx,cont);
67         }
68         printf("%lld
",maxx);
69     }
70 }
原文地址:https://www.cnblogs.com/stranger-/p/7819839.html