被3整除

今天这个题目的解决方案很简洁到惊人。但是使用这种方案解决此题需要一定的数学知识。话不多说,上题目。

这是2019年网易的编程题。

题目描述

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

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

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

输入描述:

输入包括两个整数lr(1 <= l <= r <= 1e9), 表示要求解的区间两端。

输出描述:

输出一个整数, 表示区间内能被3整除的数字个数。

示例1

输入

 

2 5

输出

 

3

说明

12, 123, 1234, 12345...
其中12, 123, 12345能被3整除。

1.分析题目

这个“神奇的数列”的排列规律是:第n个数的大小是在纸上从左到右依次写下从1到n所形成的整数。

题目要求给出两个数字,一个是起始位置,一个是结束位置。求出这个数列的两个位置之间(包含两端点)能够被3整除的数。

下面开始寻找这个数列中的规律。

假设这个数列中第i个数为a[i](i>=2,i为整数),第i个数对3取余为last[i]。可以得到a[i]与a[i-1]的关系。

a[i]=a[i-1]*10^k+i;

k为i的十进制位数。显然可以看出。

Last[i]

=a[i]%3

=(a[i-1] *10^k+i)%3

=(a[i-1] *(10^k-1)+ a[i-1]+i)%3     //由这一步可以知道n*10^k%3=n%3

=(a[i-1]+i)%3      //k>=1,(10^k-1)总是能够被3整除的

显然可以上式也等于

=(a[i-1] %3+i%3)%3  //两个和对3取余等于分别对3取余,余数相加再对3取余。

推论1

last[i]= (last[i-1]+i%3)%3;

数学归纳法论证last[i]的规律。

当n = 0的时候:

last[0] = 0、last[1] = 1、last[2] = 0成立

 

假设last[3n]=0, last[3n+1]=1, last[3n+2]=0。

讨论last[3(n+1)]=( last[3n+2]+ 3(n+1)%3)%3=(0+0)%3=0

last[3(n+1)+1]= ( last[3(n+1)]+ (3(n+1)+1)%3)%3=(0+1)%3=1

last[3(n+1)+2]= ( last[3(n+1)+1]+ (3(n+1)+2)%3)%3=(1+2)%3=0

可证:

当n>=1时,

last[3n]=0, last[3n+1]=1, last[3n+2]=0成立。

可见当i%3=1时,last[i]=1。

即,在该数列中,连续每三个数中存在一个不能被3整除的元素。

位置n之前(包括n)不能被3整除的元素的个数为(n+2)/3

神奇的数学归纳法!

这样要求输入数据l,r两个位置之间有多少个能够被3整除的数就好计算了。

从l到r一共有l-r+1个元素。

r之前包括r在内的元素中有(r+2)/3个不能被3整除。

l-1之前包括r在内的元素中有(l-1+2)/3个不能被3整除。

二者相减即为l到r之间不能能被3整除的元素个数。(r+2)/3-(l-1+2)/3

l到r之间能被3整除的元素个数为l-r+1-(r+2)/3+(l-1+2)/3

 

 

源代码如下:

 

#include<stdio.h>

int main()

{

    int l, r;

    while(EOF!=scanf("%d %d", &l, &r))

        printf("%d\n", r-l+1-(r+2)/3+(l-1+2)/3);

    return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值