【题目描述】
给出正整数n,m,区间[n,m]内的无平方因子数有多少个?
整数p无平方因子,当且仅当不存在k>1,使p是k^2的倍数,1<=n<=m<=10^12,m-n<=10^7
【输入格式】
两个整数n,m
【输出格式】
[n,m]间的无平方因子数的个数
【样例输入】
1 5
【样例输出】
4
【提示】
在此键入。
【来源】
刘汝佳《入门经典》
题意 : 对于所给区间,询问没有平方因子的数有多少个?
思路分析 : 这个题的思想类似区间素数筛,首先将 2 到 sqrt(m)的素数全部找到,然后将所求区间内是素数平方倍数的数全部去掉,用一个数组去保存,很关键的一点是 区间的长度时不超过 1e7 的,因此只需要开一个这样长度的数组即可,计算的时候离散即可。
素数定理 : cnt(x) 约等于 x/(lnx) 。
代码示例 :
#define ll long long const int maxn = 1e6+5; const int mm = 1e7+5; const int mod = 1e9+7; const double eps = 1e-9; const double pi = acos(-1.0); const int inf = 0x3f3f3f3f; ll n, m; bool pt[maxn]; bool f[mm]; void init(){ memset(pt, true, sizeof(pt)); for(ll i = 2; i <= sqrt(m); i++){ if(pt[i]){ for(ll j = i+i; j <= sqrt(m); j += i){ pt[j] = false; } } } //pt[1] = false; } int main() { freopen("non.in", "r", stdin); freopen("non.out", "w", stdout); cin >> n >> m; if (n > m) swap(n, m); init(); memset(f, true, sizeof(f)); for(ll i = 2; i <= sqrt(m); i++){ if (pt[i]){ for(ll j = i*i*((n+i*i-1)/(i*i)); j <= m; j += i*i){ f[j-n] = false; // 离散 } } } int cnt = 0; for(ll i = 0; i <= m-n; i++) if (f[i]) cnt++; printf("%d ", cnt); return 0; }