问题描述:
小Q得到一个神奇的数列:
1, 12, 123,...12345678910,1234567891011...
。并且小Q对于能否被3整除这个性质很感兴趣。
小Q现在希望你能帮他计算一下从数列的第
l
个到第r
个(包含端点)有多少个数可以被3
整除。
输入描述:
输入包括两个整数
l
和r(1 <= l <= r <= 1e9)
, 表示要求解的区间两端。
输出描述:
输出一个整数, 表示区间内能被
3
整除的数字个数。
样例输入:
2 5
样例输出:
3
说明:
12, 123, 1234, 12345...
其中12, 123, 12345能被3整除。
第一次思考时的思想:
我一开始看到这题的时候懵逼了。前面看上去还挺有规律的,咋
123456789
之后就成了12345678910
了?后来想了想10
是十。好了,开始设置一个base
,base
是l
之前的值,然后开始不断的遍历,%3
,如果能整除,则计数器+1
.然后这个只过了40%
的样例。
第二次思考的思想:
看到了数据量,
1e9
,所以用这种方式肯定是不行的。在python
中这样能过40%
的样例,如果在c++
中,40%
都够呛,因为肯定超c++的int了(1e9是指位数是1e9,已经很可怕了)。所以开始穷则思变。发现个规律,把一个数拆分成数字(注意910应该拆分成9,10),如果数字之和是3的倍数,那么这个数肯定能%3.
这样也不行,因为位数1e9,这样的话还是会有可能超int,只是比第一次的%3效率要高,这样可以过70%
的样例。
第三次思考的思想:
上个解法的主要瓶颈是在cur(待%3的数)超int,所以我们要从这儿改进。我们发现,我们没必要把所有的位上的数都加起来,每一位%3后的余数与下一位相加之后的效果也是一样的。(这样是很容易想到的,我们在做除法的时候,就是这个过程)
我们改进之后发现过了80%
,有的样例过不了。为啥呢?因为他妈的计数器count竟然超了int!!!妈了个巴子坑爹。
第四次思考的思想:
怎么搞定这个呢?大数相加算法。把
count
存储在数组中模拟大数加法,最后输出。懒得写这个算法了。python的int不会超范围,如果python的int都搞不定,那么久过分了。把算法迁移到python,过了70%
。python的速度拖了后腿。然后发现牛客竟然有pypy,果断用之,过了100%
。
第五次思考的思想:
万一是赛码网这种没有pypy的沙雕平台怎么办?只能用C++实现大数加法了吗?
不是的。我们首先多写几项,找找规律。1,12,123,1234,12345,123456,1234567,12345678,123456789,12345678910,1234567891011
我们发现,如果从1开始,3个数一组的话,第一个数不能被3整除,第二个数和第三个数都可以被3整除。究其原因我们发现,因为12、15、18都是3的倍数。
我们可以利用这个规律写出高效的代码,用python运行(因为count肯定是超c++的int的,不想实现大数算法只能这么做)。做法:(r-l+1)//3*2
先把肯定能被3
整除的拿到。(r-l+1)%3
的值可能是0,1,2
。如果是0的话,不用作任何操作。如果不是0,则需要判断l的位置。如果l%3==0
,则(r-l+1)%3
为1
和2
时都应当count+1
。如果l%3==1
,则(r-l+1)%3
为1
时,不作任何操作。为2
时,count+1
.
如果i%3 == 2
,则(r-l+1)%3
为1
时count+1
,否则count+2
.(画个图秒懂)
第三次c++代码:
#include
using namespace std;
int main(){
int l,r;
cin>>l>>r;
int cont = 0;
int last = (1+l)*l/2;
int yushu = last%3;
if(yushu == 0){
cont ++;
}
l ++;
while(l<=r){
yushu += l;
yushu %= 3;
if(yushu == 0){
cont++;
}
l++;
}
cout<
第四次交到pypy的代码:
def solution():
l,r = input().split()
l,r = int(l),int(r)
cont = 0
last = (1+l)*l//2
yushu = last%3
if yushu == 0:
cont += 1
l += 1
while l <= r:
yushu += l
yushu %= 3
if yushu == 0:
cont += 1
l += 1
print(cont)
solution()
第五次,python3也能过100%的代码:
def solution():
l,r = input().split()
l,r = int(l),int(r)
curs = 0
curs = (r-l+1)//3*2
yushu = (r-l+1)%3
offset = l%3
if yushu == 0:
pass
elif offset == 0:
curs += 1
elif offset == 1:
if yushu == 2:
curs += 1
elif offset == 2:
if yushu == 1:
curs += 1
elif yushu == 2:
curs += 2
print(curs)
solution()
经验与教训:
第一,注意审题,要考虑到数据量与溢出问题。
第二,对于这种规律题,疯狂找规律,有枣没枣打一杆。
第三,对于程序的基础组件(大数加法)等,有必要写成自己的工具包,到时候直接套用模板即可。(针对某些情况下oj对python不友好的情况)
问题描述:
平面内有n个矩形, 第i个矩形的左下角坐标为(x1[i], y1[i]), 右上角坐标为(x2[i], y2[i])。
如果两个或者多个矩形有公共区域则认为它们是相互重叠的(不考虑边界和角落)。
请你计算出平面内重叠矩形数量最多的地方,有多少个矩形相互重叠。
问题分析:
这题说实话把我难住了。我画了图1这样的图,发现最多重叠区域的左下角一定是某个矩形的左下角(这当然是错误的,但是根据我画的图还真就是正确的)。
后来只过了30%。然后想了想,是不是算法不对?还真不对。于是我又画了一张图2,发现重叠区域是由任意一个矩形的底边和任意一个矩形的左边组合成的。于是改进算法,给出所有底边和左边的组合去判断是否在所给的矩形中,统计个数即可。
def solution():
n = int(input())
x1 = list(map(lambda x:int(x),input().split()))
y1 = list(map(lambda x:int(x),input().split()))
x2 = list(map(lambda x:int(x),input().split()))
y2 = list(map(lambda x:int(x),input().split()))
res = 0
for x in x1:
for y in y1:
cont = 0
for j in range(n):
if x1[j]<=x
问题描述:
牛牛总是睡过头,所以他定了很多闹钟,只有在闹钟响的时候他才会醒过来并且决定起不起床。从他起床算起他需要X分钟到达教室,上课时间为当天的A时B分,请问他最晚可以什么时间起床
输入描述:
每个输入包含一个测试用例。 每个测试用例的第一行包含一个正整数,表示闹钟的数量N(N<=100)。
接下来的N行每行包含两个整数,表示这个闹钟响起的时间为Hi(0<=A<24)时Mi(0<=B<60)分。
接下来的一行包含一个整数,表示从起床算起他需要X(0<=X<=100)分钟到达教室。
接下来的一行包含两个整数,表示上课时间为A(0<=A<24)时B(0<=B<60)分。 数据保证至少有一个闹钟可以让牛牛及时到达教室。
输出描述:
输出两个整数表示牛牛最晚起床时间。
思路:
将时间全部转换成分钟,然后逆向排序遍历即可。
AC代码:
def solution():
n = int(input())
minutes = []
for i in range(n):
hour,minute = input().split()
hour,minute = int(hour),int(minute)
minuter = hour*60 + minute
minutes.append((hour,minute,minuter))
minutes.sort(reverse=True)
adds = int(input())
target_h,target_m = input().split()
target_h,target_m = int(target_h),int(target_m)
target_m += target_h*60
for i in minutes:
if i[2] + adds <= target_m:
print(i[0],i[1])
break
solution()
随机测试:随机测试是根据测试的经验在无测试用例的情况下进行的测试。
UDP在传输数据的时候对报文长度有要求。
一个线程可以创建和撤销另一个线程,进程是系统进行资源分配和调度的基本单位,而线程是CPU调度和分配的基本单位,一个进程中的多个线程共享资源,而线程不拥有系统资源。
死锁的产生源于系统资源不足和进程推进顺序不当,死锁是指多个进程因抢占资源而发生的一种阻塞且相互等待的现象,可以通过终止和撤销进程来解除死锁,银行家算法用在避免死锁策略中。
基于哈希算法在信息安全中主要应用在:
n趟快排题目:n趟快排之后,至少有n个元素处于最终位置上。所以解这类题先手动将数组有序化,对比每个选项的数组的对应位置与有序化的对应位置的相等元素的个数即可。