cf 226b 唯美思维题~.cpp

题意:

  给出n个数,让你用最少次数把所有的数都摞成一堆。

  其中当把arr[i]摞在第j堆上时,得扣分arr[i]

  题目有要求每个数上面不许摞超过k次,有m个k,让你求出m种情况下限制为k时的最优解,即最少扣分。

思路:

  经过多次推算会发现,如果要最后扣分最少,则应该尽量让arr[i]小的摞的次数比较多,而arr[i]大的摞的次数比较少。

  然后还有一个规律是,如果想让扣分最少,那每次应该尽量让值大的堆上摞的次数比较多,本身则尽量少摞。即尽量满足 一次摞足够多的物品。

Tips:

  如果k = 1,则答案就是arr[1] + (arr[1]+arr[2]) + (arr[1]+arr[2]+arr[3]) + (arr[1] +...+arr[i]) + (arr[1]+...+arr[i]+...+arr[n-1])//因为最后且最大的一摞不用动~所以只需要加到arr[n-1]

  否则答案就是一次摞尽量多的物品,为了令大的物品移动尽量少的次数,我们从倒数第二个到倒数第k+1个开始算,arr[n-1]~arr[n-1-k]只需要移动一次,arr[n-1-k]~arr[n-1-k-k*k]只要移动2次..and so on~~//因为1个上面可以摞k个..所以k个上面可以摞k*k个..所以以倍数的方式递增..

  优化的方法是先计算出从第0个到第i个的和,这样就可以算出其中任意一段的和了。

  所以答案就是while循环算出来的..

Code:

View Code
 1 #include <stdio.h>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <ctime>
 5 using namespace std;
 6 
 7 long long sum[100010];
 8 long long arr[100010];
 9 
10 int main()
11 {
12     int n, q, k;
13     long long ans, tans, tk;
14     int tmp, tn;
15     while(EOF != scanf("%d", &n)) {
16         tans = 0;
17         for(int i = 1; i <= n; ++i)
18             scanf("%lld", &arr[i]);
19         //printf("_\n");
20         sort(arr+1, arr+n+1);
21         sum[0] = 0;
22         for(int i = 1; i <= n; ++i) {
23             sum[i] = sum[i-1]+arr[i];
24             if(i != n) tans += sum[i];
25         }
26         scanf("%d", &q);
27         while(q--) {
28             ans = 0;
29             tmp = 1;
30             tn = n-1;
31             scanf("%d", &k);
32          //   printf("%d__\n",k);
33             tk = k;
34             if(k != 1) {
35                 while(tn >= tk) {
36                     ans += (sum[tn]-sum[tn-tk])*tmp;
37                     tn -= tk;
38                     tk *= k;
39                     tmp++;
40                 }
41                 ans += (sum[tn]-sum[0])*tmp;
42             } else ans = tans;
43             printf("%lld%c", ans, q != 0?' ':'\n');
44         }
45     }
46     return 0;
47 }

链接:http://www.codeforces.com/problemset/problem/226/B

原文地址:https://www.cnblogs.com/Griselda/p/2963912.html