/* 为[l,r]区间内有多少个数是区间[x,y]中的数的和 1 <= x, y, l, r <= 10^8 x <=y, l <= r 如果范围没这么大的话,对[x,y]这y-x+1个物品进行完全背包,找出覆盖了那些位置 现在数据这么大,背包不可行 但是,注意到[x,y]这是一个连续的区间,可以算出他们会覆盖的数是: [x,y] , [2x,2y] [kx, ky] 这样的话,我们要找满足[l,r]中的数,只要用f[r] - f[l-1] f[x]表示[1,x]中被上面那些数覆盖的个数
要注意的是,有可能[(k-1)x, (k-1)y]与[kx,ky]有重叠部分(即(k-1)y>=kx) 只要一开始重叠了,之后的所有点都会被覆盖了
数据比较大,有些判断需要用double */ #include<iostream> #include<cstring> #include<map> #include<algorithm> #include<stack> #include<queue> #include<cstring> #include<cmath> #include<string> #include<cstdlib> #include<vector> #include<cstdio> #include<set> #include<list> #include<numeric> #include<cassert> #include<sstream> #include<ctime> #include<bitset> #include<functional>
using namespace std;
long long gao(long long x, long long y, long long z, long long k) { long long l = 0, r = z; while (l <= r) {//find first l*y >= z long long m = (l+r)/2; if ((double)m*y < z) l = m+1;//要用double else r = m-1; } long long ans = 0; //[x,y] [2x,2y] [(l-1)x, (l-1)y], [lx, ly] if (l >= k) { ans = (y-x)*(k-1)*k/2 + (k-1) + (k*x > z ? 0 : z-k*x+1); } else { ans = (y-x)*(l-1)*l/2 + (l-1) + (l*x > z ? 0 : z-l*x+1); } return ans; }
int main() { #ifndef ONLINE_JUDGE //freopen("in.txt","r",stdin); #endif for (long long x, y, l, r; cin>>x>>y>>l>>r; ){ if (r < x ) { cout<<0<<endl; continue; } if (x == y) { cout<<r/x - (l-1)/x << endl; continue; } long long lk = 1, rk = y; while (lk <= rk) { long long mk = (lk+rk)/2; //要用double if ((double)mk*x > ((double)mk-1)*y) lk = mk + 1; else rk = mk-1; } //[rk*x, oo)
cout<<gao(x, y, r, rk) - gao(x, y, l-1, rk)<<endl; } return 0; }
|