题目描述
小Q得到一个神奇的数列: 1, 12, 123,...12345678910,1234567891011...。
并且小Q对于能否被3整除这个性质很感兴趣。
小Q现在希望你能帮他计算一下从数列的第l个到第r个(包含端点)有多少个数可以被3整除。
输入描述:
输入包括两个整数l和r(1 <= l <= r <= 1e9), 表示要求解的区间两端。
输出描述:
输出一个整数, 表示区间内能被3整除的数字个数。
题目的意思是,给出一个序列:1,12,123,1234,12345……即第i个数是在第i-1个数的末尾加上i。
一个数能否被3整除,其实在小学就有接触过:各个数位上的数字和能被3整除,那么这个数能被3整除。
喵哥在做这道题的时候想过把一个数字的每一位加起来,然后看结果是否可以被3整除。但是,发现这样做很麻烦,而且会超出时间限制。然后,喵哥开始在纸上写写画画,发现一个秘密:
对于一个整数,从其中取出连续的子数,把这些子数相加,如果得到的结果可以被3整除,那么这个数就可以被3整除。
例如:
777
77+7=84
证明如下:
假设有一个4位数abcd,其中ab+cd可以被3整除,证明abcd可以被3整除。
必然被3整除,而ab+cd被3整除是条件,所以abcd可以被3整除。
回到题目中去,现在只要把1到 l 的数相加就可以得到第 l 个数。对于从 l 到 r 的数,每次累加一个对应的数字,然后判断是否可以被3整除即可。
#include <bits/stdc++.h>
using namespace std;
long long getBaseNum(long long end){
return (1+end)*end/2;
}
int main(){
long long l, r;
cin >> l >> r;
long long baseNum = getBaseNum(l);
long long count = 0;
for(int i = l + 1; i <= r + 1; i++){
if(baseNum % 3 == 0)
count++;
baseNum += i;
}
cout << count;
return 0;
}
其实,这样的解题思路还是不够好,对于很极端的例子,运行时间还是蛮长的。仔细观察会发现,这个序列可以被3整除的位置是有规律的:
数字 | 1 | 12 | 123 | 1234 | 12345 | 123456 | 1234567 | 12345678 | 123456789 |
余数 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
可以发现:每3个数中有一个是不可以被3整除的,只要用r - l +1减去不可以整除数字的数量,就可以得到被3整除的数量。
对于i,前i个数字有个数字是不可以被3整除的。
这样计算就更快了。
#include <bits/stdc++.h>
using namespace std;
int main(){
int l,r;
cin >> l >> r;
cout << (r - l + 1 - ((r + 2) / 3 - (l - 1 + 2) / 3));
return 0;
}
其他的一些数字的整除特征可以参考:能被2、3、4、5、6、7、8、9等数整除的数的特征