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;
}