B 排序+贪心
首先想到,选择的mk个数字一定是最大的,因为无论如何分组,总有区间是包含前mk大的数字的。
然后是分组,分组的情况不是唯一的(开始的时候分组一直和样例不一样,改了好多次)后来发现分组可以不一样QAQ

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
#include<vector>
using namespace std;

struct node
{
    int s,num;
}a[200100];

int n,m,k;
long long sum;

bool cmp1(node k,node l)
{
    return k.s > l.s;
}

bool cmp2(node k,node l)
{
    return k.num < l.num;
}

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i = 0;i < n; ++i)
    {
        scanf("%d",&a[i].s);
        a[i].num = i + 1;
    }
    sort(a,a + n,cmp1);
    sum = 0;
    for(int i = 0;i < m * k; ++i) sum += a[i].s;
    printf("%lld\n",sum);
    sort(a,a + m * k,cmp2);
    int t = m - 1;
    for(int i = 1;i < k - 1; ++i)
    {
        printf("%d ",a[t].num);
        t += m;
    }
    printf("%d\n",a[t].num);
    return 0;
}

C 数学 最大质因子
之前做过一个十进制下求l到r中有多少个0的题,当时是考虑到10 = 2 * 5,所以必须要有1个5 和一个 2 才会有1个0,因为l到r 中2 肯定比 5 多,就是看l 到 r里面的数字i,里面含有多少个数字5
那么这个题呢,把10 换成了b ,其实也一样,只要分解质因数b = p1 ^a1* p2^a1 * p3 ^a3…*pn ^an,找到n!里面p1、p2、… pn里面出现的次数c1 c2 c3…cn
0的个数就是min(c1/a1,c2/a2,…,cn/an)

D 区间DP
(1)将[i…j]染成i处的颜色或者j处的颜色所用次数最少
(2)如果a[i] 与 a[i + 1] 颜色相等,dp[i][j] 可以由 dp[i + 1][j] 得到,a[j]与a[j - 1]相等同理
(3)如果a[i] == a[j], f[i][j] 可以由 f[i + 1][j - 1] + 1 得到
(4)以上都不满足,f[i][j] 可以由 f[i + 1][j] + 1 或 f[i][j - 1] 得到

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
#include<vector>
using namespace std;

int a[5010];
int f[5010][5010];
int n;

int main()
{
    scanf("%d",&n);
    for(int i = 1;i <= n; ++i) scanf("%d",&a[i]);
    memset(f,0x3f,sizeof(f));
    for(int i = 0;i <= n; ++i) f[i][i] = 0;
    for(int len = 1;len <= n; ++len)
        for(int i = 1;i <= n && i + len <= n; ++i)
        {
            int j = i + len;
            if(a[i] == a[i + 1]) f[i][j] = f[i + 1][j];
            else if(a[j] == a[j - 1]) f[i][j] = f[i][j - 1];
            else if(a[i] == a[j]) f[i][j] = min(f[i][j],f[i + 1][j - 1] + 1);
            else
            {
                f[i][j] = min(f[i][j],f[i + 1][j] + 1);
                f[i][j] = min(f[i][j],f[i][j - 1] + 1);
            }
        }
    printf("%d\n",f[1][n]);
    return 0;
}