1. 算法竞赛中的动态规划实战:洛谷P10262亲朋数解析
这道题目来自洛谷的GESP样题六级题库,编号P10262。作为一道典型的动态规划问题,它不仅考察选手对基础算法的掌握程度,更考验将数学思维转化为高效代码的能力。我在准备蓝桥杯竞赛时,这道题曾让我卡壳近两小时,后来才发现关键在于余数性质的应用。
亲朋数问题的核心是统计数字串中所有连续子串对应的数值能被给定整数p整除的数量。以样例"102"为例,其5个有效子串分别是"1"(余数1)、"10"(余数0)、"102"(余数0)、"0"(余数0)、"02"(余数0)。注意单独的数字"2"虽然数值为2,但在原串中作为"102"的结尾部分已经被统计过。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题重述与数学建模
2.1 问题形式化定义
给定数字串S(长度L≤10^6)和整数p(2≤p≤128),需要统计所有连续子串对应的数值是p的倍数的数量。例如S="12342",p=2时,有效子串包括:
- "12"(12÷2=6)
- "1234"(1234÷2=617)
- "12342"(12342÷2=6171)
- 两个不同位置的"2"(索引2和5)
- "234"(234÷2=117)
- "2342"(2342÷2=1171)
- "34"(34÷2=17)
- "342"(342÷2=171)
- "4"(4÷2=2)
- "42"(42÷2=21)
2.2 暴力解法的时间复杂度
最直观的做法是枚举所有L(L+1)/2个子串,逐个计算数值并检查是否能被p整除。对于L=10^6,子串数量约为5×10^11,即使每个检查只需1μs,也需要约5.8天——显然不可行。
2.3 关键数学性质
利用模运算性质:(a*10 + b) mod p = ((a mod p)*10 + b) mod p。这意味着我们可以动态维护当前数字串的余数,而不需要计算完整的数值。例如:
- "102"的处理过程:
- 读取'1':当前余数=1 mod 2=1
- 读取'0':新余数=(1*10+0) mod 2=0 → 找到有效子串"10"
- 读取'2':新余数=(0*10+2) mod 2=0 → 找到"102"和"2"
3. 动态规划解法详解
3.1 状态定义
定义两个数组f和g(大小均为p)
