小白月赛三 妹纸
题目链接:https://www.nowcoder.com/acm/contest/87/D
来源:牛客网
题目描述
XHRlyb发明了一类数,叫做妹纸数。
假设xi∈[p,q],yi∈[u,v],且xi与yi均为整数,我们称这区间[p,q]相对于区间[u,v]的妹纸数为
∑
i
=
p
q
=
i
m
o
d
v
m
o
d
(
v
−
1
)
m
o
d
…
m
o
d
(
u
)
\sum_{ i=p }^ { q } = i~ mod~ v~mod~(v-1)~mod…~mod~(u)
i=p∑q=i mod v mod (v−1) mod… mod (u)
XHRlyb想让Cwbc帮她快速计算多组区间(a,b]相对于区间[l,r)的妹纸数。
Cwbc显然是愿意帮助她的,但他知道你不想解决这个问题,于是就把这个问题交给了你。
聪明的你在仔细阅读题目后,一定可以顺利的解决这个问题!
输入描述:
输入数据有多行,每行有四个整数,a,b,l,r。
输出描述:
输出数据应有多行,每行有一个数,表示答案。
示例1
输入
复制
2 3 1 2
输出
0
说明
任何数对1取模后的结果都为0。
示例2
输入
3 6 2 4
输出
1
备注:
a ≤ b,l ≤ r。
a,b,l,r∈[1,10^6]。
1 ≤ 数据组数 ≤ 1000。
解题思路:
对于区间求和的问题我们可以把它转化为求差值来算:比如我们要求自然数5-10的和sum,我们就可以把它转化为先求1-10的和记作sumA,再求1-4的和记作sumB,然后sum=sumA-sumB,显然我们也可以把这道题转化成这种形式,因为题中要求的区间为(a,b],所以我们可以先求出1–p对于区间[l,r)求余的和,在求出1–q区间[l,r)求余的和,然后做差即可。显然对于求1–p和1–q对于区间区间[l,r)求余的和是一个难题,其实仔细想一想就能得出一个结论:一个数对于一个左闭右开的区间[l,r)求余的到的最大的数就是L-1。因为区间的不确定性,还分为两种情况:1.若x<r,则需要判断x%(r)与(L)的大小并求出最小值minn。在求1—minn的和。2.若x>=r,则直接算出1—L的和sum在乘以x/r,然后在加上情况1(因为x/r不一定被整除,不被整除的话x/r的余数正好符合情况1)
因为刚开始写博客,还不能较好的把自己的想法表达出来,若有一些语句表达不当,请留言指出。
AC代码:
#include <iostream>
using namespace std;
typedef long long LL;
LL a,b,l,r;
LL Sum(LL x) {//计算1---x的和
return x*(x+1)>>1;
}
LL solve(LL x) {
return Sum(l)*(x/r)+Sum(min(x%r,l));//因为x<r的时候x/r等于0,所以可以把两种情况写到一起。
}
int main() {
while (cin>>a>>b>>l>>r) {
l--,r--;//因为区间是左闭右开所以对于l求余的最大值即为l-1,r--是表示r能取到的最大值
cout<<(solve(b)-solve(a))<<endl;
}
return 0;
}