/* 為[l,r]區(qū)間內(nèi)有多少個數(shù)是區(qū)間[x,y]中的數(shù)的和 1 <= x, y, l, r <= 10^8 x <=y, l <= r 如果范圍沒這么大的話,對[x,y]這y-x+1個物品進行完全背包,找出覆蓋了那些位置 現(xiàn)在數(shù)據(jù)這么大,背包不可行 但是,注意到[x,y]這是一個連續(xù)的區(qū)間,可以算出他們會覆蓋的數(shù)是: [x,y] , [2x,2y] [kx, ky] 這樣的話,我們要找滿足[l,r]中的數(shù),只要用f[r] - f[l-1] f[x]表示[1,x]中被上面那些數(shù)覆蓋的個數(shù)
要注意的是,有可能[(k-1)x, (k-1)y]與[kx,ky]有重疊部分(即(k-1)y>=kx) 只要一開始重疊了,之后的所有點都會被覆蓋了
數(shù)據(jù)比較大,有些判斷需要用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; }
|