//yukicoder@cpp17 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using ll = long long; using P = pair; const ll MOD = 998244353; const ll MODx = 1000000007; const int INF = (1<<30)-1; const ll LINF = (1LL<<62LL)-1; const double EPS = (1e-10); P ar4[4] = {{0,1},{0,-1},{1,0},{-1,0}}; P ar8[8] = {{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}}; template vector make_vector(size_t a, T b) { return vector(a, b); } template auto make_vector(size_t a, Ts... ts) { return vector(a, make_vector(ts...)); } /* 確認ポイント cout << fixed << setprecision(n) << 小数計算//n桁の小数表記になる 計算量は変わらないが楽できるシリーズ min(max)_element(iter,iter)で一番小さい(大きい)値のポインタが帰ってくる count(iter,iter,int)でintがiterからiterの間にいくつあったかを取得できる */ /* function corner below */ /* Function corner above */ /* comment outed because can cause bugs __attribute__((constructor)) void initial() { cin.tie(0); ios::sync_with_stdio(false); } */ template struct BIT{//1_Indexed int n; vector bit; BIT(){} BIT(int n_):n(n_+1),bit(n,0){} void set(int n_){ n = n_; bit.assign(n,0); } T sum(int a){ T ret = 0; for(int i = a; i > 0; i -= i & -i) ret += bit[i]; return ret; } void add(int a,T w){ for(int i = a; i <= n; i += i & -i)bit[i] += w; } T query(int r,int l){ return sum(l-1)-sum(r-1); } int lower_bound(T x){ if(x <= 0){ return 0; } x--; int t = 1; while(t < n)t <<= 1; int st = 0; int base = 0; for(; t; t/=2){ if(st+t <= n && base+bit[st+t] <= x){ base += bit[st+t]; st += t; } } return st+1; } }; struct SieveEratos{ int N; vector minp; vector primes; map invprimes; SieveEratos(){} SieveEratos(int n):N(n+1){ generate(); } void set(int n){ N = n; generate(); } void generate(){ minp.assign(N+1, N+2); minp[0] = minp[1] = -1; for(int i = 2; N >= i; i++){ if(minp[i] == N+2){ primes.push_back(i); invprimes[i] = primes.size(); minp[i] = i; for(int j = i+i; N >= j; j+=i){ minp[j] = min(i, minp[j]); } } } } bool operator[](int x){return minp[x] == x;} }; // 整数型を取得することを想定 template T CeilExactSqrt(int c, T x){ T mn = 0; T mx = x; while(mx-mn > 1){ T ce = (mn+mx)/2; T nw = 1; for(int i = 0; c > i; i++){ if(x/ce < nw){ mx = ce; break; } nw *= ce; if(i+1 == c && x == nw){ mx = ce; } } if(mx != ce)mn = ce; } return mx; } template T FloorExactSqrt(int c, T x){ T mn = 0; T mx = x; while(mx-mn > 1){ T ce = (mn+mx)/2; T nw = 1; for(int i = 0; c > i; i++){ if(x/ce < nw){ mx = ce; break; } nw *= ce; } if(mx != ce)mn = ce; } return mn; } struct MeisselLehmer{ long long N; long long alpha; SieveEratos sieve; BIT varphiTable; struct d{ long long m,b; int cof; bool operator<(const d x)const{ if(m == x.m) return b < x.b; return m < x.m; } }; vector varphiQueue; MeisselLehmer(long long n): N(n){ alpha = ceil(pow(N, 0.34)); sieve.set(N/alpha+10); } long long varphiLoop(long long n, long long a, int cof = 1){ if(a == 0){ return n; }else{ if(n/sieve.primes[a-1] <= N/alpha){ if(n/sieve.primes[a-1] >= 2){ varphiQueue.push_back({n/sieve.primes[a-1], a-1, cof*-1}); return varphiLoop(n, a-1, cof); }else{ return varphiLoop(n, a-1, cof) - varphiLoop(n/sieve.primes[a-1], a-1, cof*-1); } }else{ return varphiLoop(n, a-1, cof) - varphiLoop(n/sieve.primes[a-1], a-1, cof*-1); } } } long long varphi(long long n, long long a){ varphiTable.set(N/alpha+1); long long val = varphiLoop(n,a); sort(varphiQueue.begin(), varphiQueue.end()); int cur = 0; for(int i = 2; N/alpha >= i; i++){ varphiTable.add(sieve.invprimes[sieve.minp[i]], 1); while(cur < varphiQueue.size() && varphiQueue[cur].m == i){ val += varphiQueue[cur].cof * (varphiQueue[cur].m - varphiTable.query(1, varphiQueue[cur].b+1)); cur++; } } varphiQueue.clear(); return val; } long long P2(long long n, long long a){ long long val = 0; int cur = sieve.primes.size()-1; for(int i = a; n/sieve.primes[a-1] > sieve.primes[i]; i++){ while((sieve.primes[cur] > n / sieve.primes[i] || (n%sieve.primes[i] == 0 && sieve.primes[cur] == n/sieve.primes[i]))){ cur--; } if(cur < i)break; val += cur-i+1; } return val; } long long count(long long n = -1){ if(n == -1)n = N; long long prevN = N; N = n; alpha = ceil(pow(N, 0.34)); if(N < 2)return 0; else if(N < 3)return 1; long long val = varphi(N, alpha) + alpha-1 - P2(N, alpha); N = prevN; return val; } }; int main(){ long long L, R;cin>>L>>R; MeisselLehmer P(2LL*R); long long val = 0; if(L != R)val += P.count(2LL*R-1) - P.count(2LL*L); val += P.count(R) - P.count(L-1); cout << val << endl; return 0; }