Problem:
問題 E Fox Number

問題文

きつねのしえるは数字について考えるのが好きである．ある日，しえるはこの世にねこの数字というものがあることを知り，自分もそのような数字が欲しくなってしまった．そこで，次の性質を満たす数字をとりあえず Fox Number と呼ぶことにした．

[性質]: 整数 N は k (≥ 1) 個の素数 p1, ..., pk と正整数 e1, ..., ek で，p1 < ... < pk，e1 ≥ ... ≥ ek を満たすものによって N = p1e1 × ... × pkek と書けるとき，Fox Number であると呼ぶことにする．

ところでしえるはこの性質をその場の思いつきで決めてしまったのでこれがどういう性質を持っているのか全くわかっていない．そこで，この数字の性質を調べるために区間 [A-B, A+B] に含まれる Fox Number の個数を出力して欲しい．

入力形式

1 行目に以下の 2 つの整数が与えられる．

A B

出力形式

1 行目に，A-B 以上 A+B 以下の Fox Number の個数を出力せよ．

制約

1 ≤ A ≤ 1012

0 ≤ B ≤ 5 × 105

入出力例

入力例 1

18 2

出力例 1

4

16 = 24, 17 = 171, 19 = 191, 20 = 22 × 51 は Fox Number である．一方で 18 = 2 × 32 は Fox Number ではない．合計して 4 つの Fox Number がある．

入力例 2

100 10

出力例 2

18

入力例 3

123456 789

出力例 3

1464

Solution in C (judge verdict: Accepted)

// AOJ 2275: Fox Number
// 2017.12.11 bal4u@uu

#include <stdio.h>
#include <string.h>
#include <math.h>

#define MAX  1000005			// sqrt(1e12)
char tbl[MAX+1];

int sz;						// max sz = 78500, prime[0] = 2, prime[78499] = 1000005
int prime[79000] = {  		// prime[168] = 1009, prime[169] = 1013, 1009^2 = 1018081
  2, 3,  5,  7, 11, 13, 17, 19, 23, 29, 
 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 
 73, 79, 83, 89, 97,101,103,107,109,113, 
127,131,137,139,149,151,157,163,167,173,
179,181,191,193,197,199,211,223,227,229, 
233,239,241,251,257,263,269,271,277,281, 
283,293,307,311,313,317,331,337,347,349, 
353,359,367,373,379,383,389,397,401,409, 
419,421,431,433,439,443,449,457,461,463, 
467,479,487,491,499,503,509,521,523,541, 
547,557,563,569,571,577,587,593,599,601, 
607,613,617,619,631,641,643,647,653,659, 
661,673,677,683,691,701,709,719,727,733, 
739,743,751,757,761,769,773,787,797,809, 
811,821,823,827,829,839,853,857,859,863, 
877,881,883,887,907,911,919,929,937,941, 
947,953,967,971,977,983,991,997,1009 };

int sqp[169] = {				// squre of prime: sqp[i] = prime[i] * prime[i]
  4, 9,25,49,121,169,289,361,529,841,961,
1369,1681,1849,2209,2809,3481,3721,4489,5041,
5329,6241,6889,7921,9409,10201,10609,11449,11881,12769,
16129,17161,18769,19321,22201,22801,24649,26569,27889,29929,
32041,32761,36481,37249,38809,39601,44521,49729,51529,52441,54289,
57121,58081,63001,66049,69169,72361,73441,76729,78961,80089,85849,
94249,96721,97969,100489,109561,113569,120409,121801,124609,128881,
134689,139129,143641,146689,151321,157609,160801,167281,175561,177241,
185761,187489,192721,196249,201601,208849,212521,214369,218089,229441,
237169,241081,249001,253009,259081,271441,273529,292681,299209,310249,
316969,323761,326041,332929,344569,351649,358801,361201,368449,375769,
380689,383161,398161,410881,413449,418609,426409,434281,436921,452929,
458329,466489,477481,491401,502681,516961,528529,537289,546121,552049,
564001,573049,579121,591361,597529,619369,635209,654481,657721,674041,
677329,683929,687241,703921,727609,734449,737881,744769,769129,776161,
779689,786769,822649,829921,844561,863041,877969,885481,896809,908209,
935089,942841,954529,966289,982081,994009,1018081 };

void sieve()
{
	int i, j, k;

	for (i = 1; i < 169; i++) {
		k = prime[i];
		for (j = sqp[i]; j < MAX; j += k) tbl[j] = 1;
	}
	for (sz = 168, i = 1009; i <= MAX; i += 2) if (!tbl[i]) prime[sz++] = i;
}

int base[1000002];
int idx [1000002];
long long pp[70];

int bsch(int x)
{
	int m, l = 0, r = sz;

    while (l < r) {
        m = (l + r) >> 1;
		if (prime[m] == x) return m;
        if (prime[m] < x) l = m + 1; else r = m;
    }
	return l-1;
}

int main()
{
	int i, k, p, ans;
	long long A, B, a, b, j, ll, rr, x;

	sieve();

	scanf("%lld%lld", &A, &B);
	a = A-B, b = A+B;
	if (b <= 1) { puts("0"); return 0; }
	if (a <= 1) a = 2;

	sz = bsch((int)sqrt((double)b));

	memset(idx, 1, sizeof(idx));
	for (i = 0; i <= sz; i++) {
		p = prime[i];
		for (k = 1, j = p; j <= b; j *= p) pp[k++] = j;
		while (--k) {
			j = pp[k], ll = j*(1+(a-1)/j), rr = j*(b/j);
			for (; ll <= rr; ll += j) {
				x = ll-a;
				if (!idx[x] || base[x] == p) continue;
				if (idx[x] < k) idx[x] = 0;
				else base[x] = p, idx[x] = k;
			}
		}
	}

	ans = 0, i = (int)(b-a+1); while (i--) if (idx[i]) ans++;
	printf("%d\n", ans);
	return 0;
}