zoukankan      html  css  js  c++  java
  • luoguP6187 [NOI Online 提高组]最小环 贪心 记忆化

    题目让我们把序列ai重新排列,使得环上任意两个距离为ki的数字乘积之和最大。 乘法与加法不同,把四个数分为两组分别计算,再求和。 比如1 2 3 4四个数 (1 + 2)+(3 + 4) ==  (1 + 3) + (2 + 4) (1 * 2) + (3 * 4)>(1*3)+(2*4) 对于乘法而言,大的数和大的数相乘,小的数和小的数相乘,能获取更大的运算结果。

    我们把这4个数,分成两部分。右上部分是11,9坐下部分是12,8这样子我们看到,最大的数,两侧是第2大和第3大的数,显然这样子,我们就不会“耽误”最大的数。

    我们刚刚注意到,如果n=12,k=3。我们似乎是要填4个独立的环。我们看到,每个颜色的环,都是独立按照刚刚的方法构造的。每个环之间没有任何影响,就是第一个环填的数是[12,9]第二个环填的数是[8,5]第三个环填的数是[4,1]

    那么n,k还有刚刚我们每次构造,互相独立的“环”的数量关系是什么呢?环数=gcd(n,k)环长=n/gcd(n,k)

    n是不变的。比如n=9,那当k=3或者k=6时,gcd(9,3)==gcd(9,6)==3,其实构造方法是完全一样的,所以我们以环长为下标,记忆化答案,

     1 #include <cstdio>
     2 #include <algorithm>
     3 using namespace std;
     4 typedef long long ll;
     5 int n,m,k;
     6 ll ans,a[210000],f[210000];
     7 int gcd(int a,int b)
     8 {
     9     if (b == 0)
    10         return a;
    11     return gcd(b,a%b);
    12 }
    13 bool cmp(ll a,ll b)
    14 {
    15     return a > b;
    16 }
    17 int main()
    18 {
    19     scanf("%d%d",&n,&m);
    20     for (int i = 1;i <= n;i++)
    21         scanf("%lld",&a[i]);
    22     sort(a + 1,a + n + 1,cmp);
    23     for (int i = 1;i <= m;i++)
    24     {
    25         ans = 0;
    26         scanf("%d",&k);
    27         if (k == 0)
    28         {
    29             for (int j = 1;j <= n;j++)
    30                 ans += a[j] * a[j];
    31             printf("%lld
    ",ans);
    32             continue;
    33         }
    34         int r = n / gcd(n,k);
    35         if (f[r] != 0)
    36         {
    37             printf("%lld
    ",f[r]);
    38             continue;
    39         }
    40         for (int c = 1;c <= n /r;c++)
    41         {
    42             ans += a[(c - 1) * r + 1] * a[(c - 1) * r + 2];
    43             ans += a[(c - 1) * r + r - 1] * a[(c - 1) * r + r];
    44             for (int j = (c - 1) * r + 1;j <= (c - 1) * r + r - 2;j++)
    45                 ans += a[j] * a[j + 2]; 
    46         }
    47         printf("%lld
    ",ans);
    48         f[r] = ans; 
    49     }
    50     return 0;
    51 }
  • 相关阅读:
    离散数学知识点总结(8)-图论
    离散数学知识点总结(7)-格
    离散数学知识点总结(6)-计数技术
    离散数学知识点总结(5)函数
    离散数学知识点总结(4)-集合
    离散数学知识点总结(3)-二元关系
    离散数学知识点总结(2)-谓词逻辑
    离散数学知识点总结(1)-命题逻辑
    镜像仓库和Harbor
    视频管理上云平台EasyNVS 2.1版本分享RTSP流和RTMP流端口发生变化是什么原因?
  • 原文地址:https://www.cnblogs.com/iat14/p/12495269.html
Copyright © 2011-2022 走看看