牛客编程巅峰赛S2第6场 - 钻石&王者 题解

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)

全部评论

相关推荐

hso_:哈哈哈哈哈哈我没offer一样在同一道题开喷了
投递深圳同为数码等公司10个岗位
点赞 评论 收藏
分享
10-25 23:12
门头沟学院 Java
点赞 评论 收藏
分享
1 收藏 评论
分享
牛客网
牛客企业服务