A
数据较小最多1e5 暴力遍历即可
B
简单斯维题 直接排序不是最小的加k就是输出-1
C
三种情况
1. 全b依旧不可过
2. 仅a就可过
3.需要a,b 二分
D
用数组存储不同糖果的个数,sort排列
从最多糖果数开始加,令ans=a[n-1] 大于等于就ans--再加,小于就ans=a[i],再加
E 见H
F
数学题: 最多取三个互补整除的数 输出最大的和
1.X 从最大开始枚举
2.Z>X Z从最大开始找,如果Z不是X的倍数 ans=x+z
3. X<Y<Z Y从大的开始找 如果Y和ZX不构成倍数关系 ans=x+y+z
G
参考链接:https://www.luogu.org/problemnew/solution/CF1183G
ai<=n 糖果类型名称<=糖果总数
用两个数组 cnt0 cnt1 分别计每种糖果0和1的数量
以及一个sa 数组为糖果种类,以每种糖果的个数对sa进行排序
预设从i=n开始不断减小,对于每个i,糖果从多的开始,如果数量大于等于i,把当前cnt1推入优先队列,取队列里最大值v推出,糖果数加i,1数加min(v,i).直到i=1。
H
参考链接:https://blog.csdn.net/mmk27_word/article/details/93999633
BUG点:
1. if(dp[i][j]>k) dp[i][j]=k; // 防止越界
2. min(dp[n][i],k)
for (int i = 0; i <= n;i++){
ans += min(dp[n][i],k) * i; //取min
k -= dp[n][i];
if(k<=0){
break;
}
}
3.pre[s[i-1]-'a'] 因为 s 是string格式 从0开始存
题解:dp做法
dp[i][j] 表示 前 i 个字母中 删掉 j 个字母 有多少种,很明显:
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
但需要去重:
往前找到和当前字母一样的第一个字母,减去那个字母导致的重复即可,因为每次计算都会减去重复,所以不用再继续往前找。
写法有二:
一、
dp[0][0] = 1;
for (int i = 1; i <= n;i++){
dp[i][0] = 1;
for (int j = 1; j <=n;j++){
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
for (int m = i - 1; m >= 1 && (j - (i - m)) >= 0;m--)
{
if(s[i-1]==s[m-1]){
dp[i][j] -= dp[m - 1][j - (i - m)];
break;
}
}
if(dp[i][j]>k){
dp[i][j] = k;
}
}
}
二、
dp[0][0] = 1;
for (int i = 1; i <= n;i++){
dp[i][0] = 1;
for (int j = 1; j <=i;j++){
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
if(pre[s[i-1]-'a'] && j>=i-pre[s[i-1]-'a'])
dp[i][j] -= dp[pre[s[i-1] - 'a'] - 1][j - (i - pre[s[i-1] - 'a'])];
if(dp[i][j]>k)
dp[i][j] = k;
}
pre[s[i-1] - 'a'] = i;
}
总结:对我来说,这套题AK较困难,GH都是难题,其余题也多出锅在答题过程中,没有别人家题解我怕是完不成了,弱鸡啊。