1 条题解
-
3
题意:给定一个长度为 L 的由数字 0 到 9 组成的数字串 S,我们要找出这个数字串中所有是给定正整数 p 的倍数的连续子串。这些连续子串可以通过从数字串 S 中选取不同的起始位置和结束位置得到,一共有 L(L+1)/2 个连续子串。然后计算出满足是 p 的倍数(即亲朋数)的子串的数量。并且强调了即使同一个子串在数字串中的位置不同,也要分别计数。例如数字串“12342”中“2”出现了两次且位置不同,就被计为两个不同的亲朋数。需要通过编程来解决计算亲朋数个数的问题。
解题思路:在主函数中,首先输入
p
和数字串S
。然后通过循环不断处理数字串。在每次循环中,先初始化新的状态数组
st_new
为 0。根据当前字符对应的数字d
,计算各种状态的更新,也就是通过计算不同位置和数字组合后对p
的余数情况,并更新相应状态数组的计数。当计算到某个余数为 0 时(即当前子串对应的数是p
的倍数),就将结果res
增加。最后将新状态数组的值赋给旧状态数组,以便在下一次循环中继续使用。最终输出的res
就是满足条件的亲朋数的总数。#include <iostream> using namespace std; // 定义字符数组 S char S[1000001]; // 定义两个长度为 128 的长整型数组,用于存储状态信息 long long st_old[128]; long long st_new[128]; int main() { int p = 0; // 定义变量 p,即要判断是否为倍数的那个数 // 输入 p cin >> p; // 输入字符串 S cin >> S; // 初始化 st_old 数组为 0 for (int i = 0; i < p; i++) st_old[i] = 0; long long res = 0; // 用于统计亲朋数的数量 // 遍历字符串 S for (int t = 0; S[t]!= '\0'; t++) { // 每次循环开始,重新初始化 st_new 数组为 0 for (int i = 0; i < p; i++) st_new[i] = 0; int d = S[t] - '0'; // 获取当前字符对应的数字 // 根据当前数字,更新各种可能的余数状态的计数 for (int i = 0; i < p; i++) st_new[(i * 10 + d) % p] += st_old[i]; st_new[d % p]++; // 单独处理当前数字本身的余数情况 // 如果当前状态下余数为 0,说明找到了一个亲朋数,增加结果计数 res += st_new[0]; // 将本次循环更新后的状态数组传递给下次循环使用 for (int i = 0; i < p; i++) st_old[i] = st_new[i]; } cout << res << endl; // 输出亲朋数的总数 return 0; }
- 1
信息
- ID
- 657
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 7
- 标签
- 递交数
- 17
- 已通过
- 9
- 上传者