取余妹子数
链接:https://ac.nowcoder.com/acm/contest/87/D
来源:牛客网
输入描述:
输入数据有多行,每行有四个整数,a,b,l,r。
输出描述:
输出数据应有多行,每行有一个数,表示答案。
备注:
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\n",ans); } }