题意:
每场比赛有x~y题,每一卷要求分为l~r题。每一卷的题数要求一样。
现在问你一卷内,可以包含一场或多场比赛的题,且刚好等于卷的大小,在l~r中有几个是可行的。
思路:
来源:http://www.cppblog.com/Yuan/archive/2011/08/01/152243.html?opt=admin
不过我按照上文博主的思路写了一发,就算用double也一样溢出,导致不能AC。
这里不得不说杰哥威武霸气。
首先我们二分出最后一个不会出现重叠的位置res。(其实可以直接算出来,在主函数中的注释便是)
二分的时候,我们要算x*mid > y*(mid-1)。转换一下,便可以得到y>(y-x)*mid,我们可以用二进制逐步计算(y-x)*mid的值,这样就算相乘溢出也可以处理了(代码中的mul函数)。
得到res后,最后进行统计即可。
code:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long uLL;
const uLL INF = 1e18+5;
uLL res;
uLL x, y, l, r;
template <class T>
T mul(T a, T b) {
T ret = 0;
while(a) {
if(a& 1) {
ret += b;
if(ret > INF) return INF;
}
a >>= 1;b <<= 1;
if(b >= INF) {
if(a) return INF;
return ret;
}
}
return ret;
}
void Binary() {
uLL l = 1, r = y;
while(l <= r) {
uLL mid = (l+r)/2;
uLL tmp = mul(mid, y-x);
//if(x*mid > y*(mid-1)){ //这里可能溢出,改成下面的写法
if(y > tmp) {
res = mid;
l = mid+1;
}
else r = mid-1;
}
}
uLL get(uLL val) {
uLL idxr = val/y;
uLL cnt = 0;
if(idxr >= res)
cnt = (1+res)*res/2*(y-x)+res+(val-res*y);
else {
cnt = (1+idxr)*idxr/2*(y-x)+idxr;
if(val%y != 0) {
uLL l = (1+idxr)*x;
cnt += (val >= l?val-l+1:0);
}
}
return cnt;
}
int main() {
//freopen("cin.txt", "r", stdin);
while(cin>>x>>y>>l>>r) {
if(x > r) {
cout<<"0"<<endl;
continue;
}
if(x == y) {
cout<<r/x-(l-1)/x<<endl;
continue ;
}
/*
res = y/(y-x);
if(y%(y-x) == 0) res--;
*/
Binary();
uLL res1 = get(r), res2 = get(l-1);
cout<<(res1-res2)<<endl;
}
return 0;
}