取余妹子数

传送门

 链接:https://ac.nowcoder.com/acm/contest/87/D
来源:牛客网

输入描述:

输入数据有多行,每行有四个整数,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)
 
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll a,b,l,r;
ll sum(ll x){
    return x*(x+1)>>1;
} 
ll getsum(ll x){
    return sum(min(x%r,l))+sum(l)*(x/r);
    //sum(min(x%r,l))这个是x<r的时候
    //sum(min(x%r,l))+sum(l)*(x/r)这个是x>=r的时候
    //就是如果x=[l,r]的时候是0,因为那个取余是倒着取的 
}
int main(){
    while(~scanf("%lld%lld%lld%lld",&a,&b,&l,&r)){
        l--;//因为能取到的最大值为l-1;
        r--;//题目中时期间[l,r) 
        ll ans=getsum(b)-getsum(a);
        printf("%lld
",ans);
    }    
} 
 
 
 
 
原文地址:https://www.cnblogs.com/lipu123/p/14387085.html