题目描述
给定一个十进制正整数 n,请问可以从 n 中截取多少种不同的子串,使得子串构成的数字是 3 的倍数。
例如:当n=1234 时,有且仅有 3,12,123,234 这四个子串是 3 的倍数。
输入格式
单个整数:表示输入的数字 n
输出格式
单个整数:表示 3 的倍数的子串数量。
数据范围
样例数据
输入:
95764
输出:
6
说明:
子串6,9,57,576,957,9576是3的倍数
输入:
1111
输出:
2
说明:
有两个111都是3的倍数
主要思想
1.80%(至于为什么是80%,是因为数据不太严谨)
首先定义string,因为C++中没有数据类型能定义。
然后开一个数组,表示每一位数字。
算每一位数字的和,用前缀和来求。
运用数学特性(如果,那么),如果(a[j]-a[i])%3==0,cnt++。
80% 代码
#include <bits/stdc++.h>
using namespace std;
int a[100005];
string s;
int cnt;
int main() {
cin >> s;
int len = s.length();
for (int i = 0; i < len; i++) {
a[i + 1] = a[i] + s[i] - '0'; //算前缀和
}
for (int i = 0; i <= len; i++) {
for (int j = i + 1; j <= len; j++) {
if ((a[j] - a[i]) % 3 == 0) {
cnt++;//如果是3的倍数,cnt增加1
}
}
}
cout << cnt;
return 0;
}
2.AC代码的养成记
1.用long long
2.余1的和余1的相减,结果余0,余2的也如此,余0的可以与余0的相减,得0,还可以自己减自己,余0
代码实现
#include <bits/stdc++.h>
using namespace std;
long long a[100005];
long long y[3];
string s;
long long ans;
//整体思想:运用前缀和,再运用数学特点*,求出答案
//*:如果A÷3=x...2,B÷3=y...2,那么A-B一定是3的倍数
int main() {
cin >> s;
int len = s.length();
for (int i = 0; i < len; i++) {
a[i + 1] = a[i] + s[i] - '0'; //算前缀和
y[a[i + 1] % 3]++;
}
ans = y[1] * (y[1] - 1) / 2 + y[2] * (y[2] - 1) / 2 + y[0] * (y[0] - 1) / 2 +
y[0]; //余1的和余1的相减,结果余0,余2的也如此,余0的可以与余0的相减,得0,还可以自己减自己,余0
cout << ans;
return 0;
}