力扣周赛313 笔记

力扣周赛313 笔记

第一题

题目:给你两个正整数 a 和 b ,返回 a 和 b 的 公 因子的数目。
如果 x 可以同时整除 a 和 b ,则认为 x 是 a 和 b 的一个 公因子。

解法:实际上相当于枚举a,b最大公因数的因子。特别要注意的是优化的方法:对于一个因子x,如果 x 2 x^{2} x2 >数字本身,那么说明n/x(另一半更小的因子)在之前肯定被枚举过了,所以不要再计数了。

c++最大公因数函数:__gcd(a,b)

第二题

沙漏的最大总和
脑瘫题

第三题

题目:给你两个正整数 num1num2 ,找出满足下述条件的整数 x

x 的置位数和 num2 相同,且
x XOR num1 的值 最小
注意 XOR 是按位异或运算。

返回整数 x 。题目保证,对于生成的测试用例, x 是 唯一确定 的。

整数的 置位数 是其二进制表示中 1 的数目。

解法:其实就是尽量消除num1中的1并且根据num2的置位数数量分情况讨论,主要记录一些位运算的方法。

1:求置位数,c++:

bitset <位数> a (unsigned long);
cout<<a.count

2: lowbit:

lowbit=x&(-x);

之后用原数减去lowbit就可以去掉最后一位的1。

3:把一个数a最后的0变成1

a = 10011
a+1 = 10100
a|=a+1;

第四题

题目:给你一个仅由小写英文字母组成的字符串 s 。在一步操作中,你可以:

删除 整个字符串 s ,或者
对于满足 1 <= i <= s.length / 2 的任意 i ,如果 s 中的 前 i 个字母和接下来的 i 个字母 相等 ,删除 前 i 个字母。
例如,如果 s = “ababc” ,那么在一步操作中,你可以删除 s 的前两个字母得到 “abc” ,因为 s 的前两个字母和接下来的两个字母都等于 “ab” 。

返回删除 s 所需的最大操作数。

解法:对字符串操作之后的子字符串可以继续操作,相当于子问题,故用dp解决。
定义 f[i] 表示删除后缀 s[i:]所需的最大操作数。ans=f[0];

根据题意,我们可以枚举删除字母的长度 j,如果 s[i:i+j] = s[i+j:i+2j],那么可以删除,此时有转移 f[i] = f[i+j] + 1。如果不存在两个子串相等的情况,则 f[i] = 1f[i] 取所有情况的最大值。

倒着计算 f[i],答案为 f[0]

class Solution {
public:
    int deleteString(string s) {
        int n = s.length();
        if (equal(s.begin() + 1, s.end(), s.begin())) // 特判全部相同的情况
            return n;
        int lcp[n + 1][n + 1]; // lcp[i][j] 表示 s[i:] 和 s[j:] 的最长公共前缀
        memset(lcp, 0, sizeof(lcp));
        for (int i = n - 1; i >= 0; --i)
            for (int j = n - 1; j > i; --j)
                if (s[i] == s[j])
                    lcp[i][j] = lcp[i + 1][j + 1] + 1;
        int f[n];
        memset(f, 0, sizeof(f));
        for (int i = n - 1; i >= 0; --i) {
            f[i]=1;
            for (int j = 1; i + j * 2 <= n; ++j)
                if (lcp[i][i + j] >= j) // 说明 s[i:i+j] == s[i+j:i+j*2],等价于最长相同前缀长度(lcp)>j
                    f[i] = max(f[i], f[i + j]+1);
        }
        return f[0];
    }
};

以上题解只是对灵神题解的总结,非原创捏1


  1. 灵神b站题解 ↩︎

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值