2019校招真题——被3整除

题目描述

小Q得到一个神奇的数列: 1, 12, 123,…12345678910,1234567891011…。

并且小Q对于能否被3整除这个性质很感兴趣。

小Q现在希望你能帮他计算一下从数列的第l个到第r个(包含端点)有多少个数可以被3整除。

输入描述:
输入包括两个整数l和r(1 <= l <= r <= 1e9), 表示要求解的区间两端。
输出描述:
输出一个整数, 表示区间内能被3整除的数字个数。

解答

当区间太大时(比如r=100),这个数不可能用double等数据类型来表示,因此只能用处理大数的方式。而被3整除的数字有一个性质,就是其每一位上数字之和能够被3整除,因此我们可以用这个性质处理这个数列。

观察前几个数字发现,数列中每3个数中肯定有两个能够被3整除。比如
12,123,1234,12345
其中12,123,12345能够被3整除,但是1234不可以。因此问题可以化简为

被3整除的个数=数列长度 / 3 * 2 + something

当数列长度不是3的整数倍时,可以单独处理数列中最后1或2个数字,判断其能否被3整除即可。整个算法能在O(1)时间内完成。下边是代码:

#include<iostream>
using namespace std;

int main(){
    unsigned long L,R;
    cin>>L>>R;
    int Len = R - L + 1;
    int NumberOf3 = Len / 3 * 2;
    int LeftNum = Len % 3;
    
    if(LeftNum==1){
        unsigned long  Sum = (1+R)*R/2;
        if(Sum%3==0) NumberOf3+=1;
    }
    else if(LeftNum==2){
        unsigned long  Sum1 = (1+R)*R/2;
        if(Sum1%3==0) NumberOf3+=1;
        unsigned long int Sum2 = R*(R-1)/2;
        if(Sum2%3==0) NumberOf3+=1;
    }
    cout<<NumberOf3<<endl;
    return 0;
}

算法中有两个地方需要注意:
1.在处理数列最后一两个数字时,需要对所有位数进行求和,因为R的最大值为 1 0 9 10^9 109,如果R为int类型时可能会造成溢出,因此需要用unsign long来声明这几个变量。
2.严格来说本题在对所有位数求和时有问题,比如说求12345678910的位数和,应该是1+2+…+9+1+0,但是算法中是1+2+…+9+10。因为加1和加10在对3求余的时候效果是一样的,所以上题算法行得通。

题目来源:https://www.nowcoder.com/practice/51dcb4eef6004f6f8f44d927463ad5e8?tpId=98&tqId=32825&tPage=1&rp=1&ru=%2Fta%2F2019test&qru=%2Fta%2F2019test%2Fquestion-ranking

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值