整除子串
整除子串
给定一个由数字组成的字符串 ,请你计算能够被 整除的 的子串数量。
子串可以包含前导 。
例如,如果 为 124 ,则满足条件的子串有 个: 12 , 4 , 24 , 124 ;如果 为 04 ,则满足条件的子串有 个: 0 , 4 , 04 。
输入格式
一个由数字组成的字符串 。
输出格式
一个整数,表示满足条件的子串数量。
数据范围
前 4 个测试点满足 。
所有测试点满足 。
输入样例1:
124
输出样例1:
4
输入样例2:
04
输出样例2:
3
输入样例3:
5810438174
输出样例3:
9
解题思路
的充分必要条件是能整除的末两位。把拆成两部分,末两位为,前面剩余的位为,即有,那么有,其中不管是什么,都能整除,因此等价于。
因此我们可以枚举区间的右端点,看前面有多少个左端点使得这个区间组成的数能够被整除,只需要看最后两位数和组成的数能否被整除,如果可以被整除,那么左端点可以取前面任何一个值(从,共个)。如果两位数不能被整除,那么无论前面取什么都不能被整除,即能够被整除的子串数为。还需要特判一下字串长度为的情况,只需要看这一位能否被整除。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 3e5 + 10; 5 6 char str[N]; 7 8 int main() { 9 scanf("%s", str); 10 11 long long ret = 0; 12 for (int i = 0; str[i]; i++) { 13 if ((str[i] - '0') % 4 == 0) ret++; // 特判长度为1的子串 14 // 子串长度大于1的情况,看末两位能否被4整除 15 if (i && ((str[i - 1] - '0') * 10 + (str[i] - '0')) % 4 == 0) ret += i; 16 } 17 18 printf("%lld", ret); 19 20 return 0; 21 }
这题还可以用dp来做。一开始太死板了,没想到当前状态是可以从上一次的哪个状态转移过来,其实可以反过来思考,可以通过当前状态可以转移到下一个的哪个状态来进行状态的计算。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 3e5 + 10; 7 8 char str[N]; 9 int f[N][4]; 10 11 int main() { 12 scanf("%s", str + 1); 13 14 for (int i = 0; str[i + 1]; i++) { 15 f[i + 1][(str[i + 1] - '0') % 4]++; // 长度为1的子串 16 for (int j = 0; j < 4; j++) { 17 f[i + 1][(j * 10 + str[i + 1] - '0') % 4] += f[i][j]; // 从当前状态转移到下一个状态 18 } 19 } 20 21 LL ret = 0; 22 for (int i = 1; str[i]; i++) { 23 ret += f[i][0]; // 结果是枚举所有以右端点结尾,构成的数模4为0的字串数量 24 } 25 printf("%lld", ret); 26 27 return 0; 28 }
参考资料
AcWing 4426. 整除子串(AcWing杯 - 周赛):https://www.acwing.com/video/3897/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16323287.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2021-05-29 常用排序算法模板