【蓝桥杯】取余

问题描述

在这里插入图片描述
在这里插入图片描述

引言

刚开始看见这题想直接暴力解,但是一看数据范围,10^14,绝对超时,翻了好多题解,看懂了这个解法,记录一下😊

思路

  • 题目要求是找出 S<=余数<=T 的个数,而余数是连续的(0,1,2……)
  • ∴可以考虑类似前缀和的方式,做减法:所有合法情况= <=T的情况 - <=(S-1)的情况
  • 设求当前合法余数个数的函数为f(A,B,x): x是限制余数大小的变量
  • res=f(A,B,T)-f(A,B,S-1)

f 怎么考虑呢?

  • 当x<0的时候:直接返回0
    ∵不可能出现余数是负数的情况
  • b∈[1,B],通过枚举除数,确定当前的余数情况:
  • 当 b<=x的时候,余数情况是:[0,b-1]<x,全部符合,所以这时候,被除数A不管是什么,都可以
    ∴res+=A
  • 当b>x的时候,这时余数会出现>x的情况,怎么考虑,举个例子:
    当A=13,b=4,x=2的时候:
    对A进行分块:
12345678910111213
1230123012301

可以发现只要可以整除一个b,就可以得到对应的余数,并且此时余数的范围是大于我们要求的,所以res+=(A//b)*(x+1)
为什么要+1?
∵ 当x=2 ,我们需要的余数有[0,1,2]三个,要把0出现的情况加上
∴要+1
同时也要考虑余数的情况,如上表,13%4=1,也符合
res+=min(A%b,x)
为什么要取最小?
∵因为这时有可能出现余数>x的错误情况,所以两个要取最小
eg:当A=9,b=5,x=2
此时res+=min(9%5,2)=2

123456789
123401234

为什么这时候不用+1了?
观察上表,能整除的情况是可整除段的最后一个,但是当前我们考虑的是取余后的余数情况,到不了被整除的0情况
∴不用+1了
综上所述,可得代码:

代码

import os
import sys
# 请在此输入您的代码 这直接暴力绝对是不行的
def f(A,B,x):
    #合法的范围:[0,T]-[0,S-1]
    if x<0:
        return 0#不合法情况
    res=0
    for b in range(1,B+1):
        if b<=x:
            res+=A
        else:
            res+=(A//b)*(x+1)+min(x,A%b)
    return res
A,B,S,T=list(map(int,input().split()))
print(f(A,B,T)-f(A,B,S-1))

在这里插入图片描述
ok,过了
—完结撒花—
记录一下解题过程,希望对大家有帮助,如果哪里有问题或者不足,请路过的朋友们帮忙指正一下~,感谢感谢!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值