A题:
看到S的长度非常小,考虑暴力+贪心的做法,依次对于每个字符,与所有的字符串作差,显然会优先改变差值小的字符,代码如下:
class Solution {
public:
/**
*
* @param k int整型 表示最多的操作次数
* @param s string字符串 表示一个仅包含小写字母的字符串
* @return int整型
*/
int f[2010];
int string2(int k, string s) {
int len=s.size(),sans=0;
for(int i=0;i<len;i++){
for(int j=0;j<len;j++)
f[j]=abs(s[i]-s[j]);
sort(f,f+len);
int ans=len,s=0;
for(int j=0;j<len;j++){
s=s+f[j];
if(s>k){
ans=j;
break;
}
}
sans=max(sans,ans);
}
return sans;
}
};时间复杂度为O(∣s∣^2 log ∣s∣)
当然也有更快的做法,留给读者考虑。
B题:
看到n和m的数据范围只有1000,考虑dp。
设dp[i][j]为前i个字符,设计了j个重音符的方案数。
分为第i个字符取或不取重音符的两个决策。
当不取重音符的时候 dp[i][j]=dp[i-1][j]
当取重音符的时候 又分为j=0,j=1和j>1三种情况
当j=0时,说明不取重音符,方案数不变。
当j=1时,说明在第1~i-1个字符中没有取重音符,无需考虑k,显然方案数+1,所以dp[i][j]=1。
当j>1时,有了k的限制,dp[i][j]就是前i-k-1个字符中取j-1个的方案数,即dp[i][j]=dp[i-k-1][j-1]。
所以,把两种决策汇总,就是dp[i][j]的答案。
最后,别忘了取模。
代码如下:
class Solution {
public:
/**
*
* @param n int整型 乐谱总音符数
* @param m int整型 重音符数
* @param k int整型 重音符之间至少的间隔
* @return long长整型
*/
int M=1000000007;
long long dp[1010][1010];
long long solve_bangbang(int n, int m, int k) {
dp[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=min(i,m);j++){
dp[i][j]=dp[i-1][j];
if(j==1)dp[i][j]=(dp[i][j]+1)%M;
if(j>1&&i-k>=0)dp[i][j]=(dp[i][j]+dp[i-k-1][j-1])%M;
}
}
return dp[n][m];
}
};时间复杂度O(nm)
同样也有更快的组合数做法,留给读者考虑。
C题:
这是一道整除分块题。
与模板题唯一不同的是,这道题向上取整。
还不了解整除分块的自行上网查找资料,这里不再赘述,这里只考虑l和r的变化。
设p为当i=l时,⌈n/i⌉的值。
r即为满足⌈n/r⌉=p是的最大值。
即为满足⌊n/r⌋=p-1的最大值。
但是还要考虑当p-1|n时,r应该比原来小1。
这样就把这道题转化成了模板题。
代码如下:
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param n int整型
* @return long长整型
*/
long long Sum(int n) {
long long ans=0;
for(int l=1,r;l<=n;l=r+1)
{
long long p;
if(n%l==0)p=n/l;
else p=n/l+1;
if(p==1)r=n;
else if(n%(p-1)==0)r=n/(p-1)-1;
else r=n/(p-1);
ans+=(r-l+1)*p;
}
return ans;
}
};时间复杂度O(√n)

京公网安备 11010502036488号