LeetCode 每日一题 2026/7/13-2026/7/19 记录了初步解题思路 以及本地实现代码并不一定为最优 也希望大家能一起探讨 一起进步目录7/13 1291. 顺次数7/14 3336. 最大公约数相等的子序列数量7/15 3658. 奇数和与偶数和的最大公约数7/16 3867. 数对的最大公约数之和7/17 3312. 查询排序后的最大公约数7/187/197/13 1291. 顺次数顺次数的每一位都比前一位大 1因此它一定是字符串 “123456789” 的连续子串。可以按长度从小到大枚举子串再转成整数判断是否在 [low, high] 范围内。设当前长度为 L则起点最多到 9-L。把 “123456789”[i:iL] 转成数字 x若 x low继续枚举若 low x high加入答案若 x high后面的同长度子串只会更大可以直接结束该长度枚举。defsequentialDigits(low,high): :type low: int :type high: int :rtype: List[int] s123456789ans[]forlengthinrange(2,10):foriinrange(0,10-length):xint(s[i:ilength])ifxlow:continueifxhigh:breakans.append(x)returnans7/14 3336. 最大公约数相等的子序列数量把每个元素有三种选择不选放入 seq1放入 seq2。这样天然保证两条子序列不相交同一个下标不会同时放进两边。定义二维 DPdp[g1][g2] 表示处理到当前下标时seq1 的 GCD 为 g1、seq2 的 GCD 为 g2 的方案数。其中 g0 表示该子序列目前为空。初始dp[0][0] 1两边都没选任何元素。转移处理元素 x从旧状态 (g1, g2) 出发方案数为 v1 不选 x保留到 (g1, g2)2 x 放入 seq1到 (gcd(g1, x), g2)3 x 放入 seq2到 (g1, gcd(g2, x))遍历完后答案是所有 g1 的 dp[g][g] 之和。因为要求两边都非空且 GCD 相等g0 不计入。defsubsequencePairCount(nums): :type nums: List[int] :rtype: int frommathimportgcd MOD10**97mmax(nums)# 预处理 gcd减少转移常数gtab[[0]*(m1)for_inrange(m1)]forainrange(m1):forbinrange(m1):gtab[a][b]gcd(a,b)dp[[0]*(m1)for_inrange(m1)]dp[0][0]1forxinnums:ndp[row[:]forrowindp]# 先继承“不选 x”forg1inrange(m1):rowdp[g1]forg2inrange(m1):vrow[g2]ifv0:continueng1gtab[g1][x]ng2gtab[g2][x]ndp[ng1][g2](ndp[ng1][g2]v)%MOD ndp[g1][ng2](ndp[g1][ng2]v)%MOD dpndp ans0forginrange(1,m1):ans(ansdp[g][g])%MODreturnans7/15 3658. 奇数和与偶数和的最大公约数前 n 个正奇数之和是 n^2。前 n 个正偶数之和是 n(n1)。要求 gcd(n^2, n(n1))。提取公因子 n得到gcd(n^2, n(n1)) n * gcd(n, n1)。因为 n 和 n1 是连续整数必互质所以 gcd(n, n1)1。因此答案直接是 n。defgcdOfOddEvenSums(n): :type n: int :rtype: int returnn7/16 3867. 数对的最大公约数之和按题意先构造 prefixGcd维护前缀最大值 mx令 prefixGcd[i] gcd(nums[i], mx)。再将 prefixGcd 升序排序从两端配对每次取最小未配元素和最大未配元素累加它们的 gcd。长度为奇数时中间元素不参与配对。defgcdSum(nums): :type nums: List[int] :rtype: int frommathimportgcd nlen(nums)prefix_gcd[0]*n mx0fori,xinenumerate(nums):mxmax(mx,x)prefix_gcd[i]gcd(x,mx)prefix_gcd.sort()ans0foriinrange(n//2):ansgcd(prefix_gcd[i],prefix_gcd[n-1-i])returnans7/17 3312. 查询排序后的最大公约数先统计 nums 中每个数的出现次数 cnt。设 mx 为最大值cntG[d] 表示所有数对中 gcd 恰好为 d 的个数。从大到小枚举 d先统计 nums 中 d 的倍数个数 v则这些数两两组成的数对 gcd 一定是 d 的倍数共有 v*(v-1)/2 对再减去 gcd 为 2d,3d,… 的对数得到恰好为 d 的对数。对 cntG 做前缀和后gcdPairs 升序序列中第 q 个位置就是第一个前缀和大于 q 的下标。每个查询用二分查找即可。defgcdValues(nums,queries): :type nums: List[int] :type queries: List[int] :rtype: List[int] fromcollectionsimportCounterfromitertoolsimportaccumulatefrombisectimportbisect_right mxmax(nums)cntCounter(nums)cnt_g[0]*(mx1)foriinrange(mx,0,-1):v0forjinrange(i,mx1,i):vcnt[j]cnt_g[i]-cnt_g[j]cnt_g[i]v*(v-1)//2slist(accumulate(cnt_g))return[bisect_right(s,q)forqinqueries]7/187/19