If an integer a is divisible by another integer b, then b is called the divisor of a.
For example: 12 has positive 6 divisors. They are 1, 2, 3, 4, 6 and 12.
Let’s define a function D(n) — number of integers between 1 and n (inclusive) which has exactly four positive divisors.
Between 1 and 10 only the integers 6, 8 and 10 has exactly four positive divisors. So, D(10) = 3.
You are given an integer n. You have to calculate D(n).
The only line contains integer n (1 ≤ n ≤ 1011) — the parameter from the problem statement.
Print the only integer c — the number of integers between 1 and n with exactly four divisors.
10
3
20
5
题意:
输入一个数n,求n以内并且只有4个不同因子的数的个数
思路:
每一个数至少存在两个因子,1和本身。
一个数仅存在四个不同的因子,那么这个数必定是某个素数的3次方或者是两个不同素数的乘积
1、n以内且是某个素数的3次方得到个数,很好求,直接将n开三次方得到x,求x以内的素数的个数即可
2、两个不同素数的乘积,枚举较小的素数a,得到b=n/a,对于不同的a,求出b以内的素数的个数,相加去重即可
那么问题就转化成了数m以内的素数个数的问题,恰好可以套用模板:hdu 5901
#include <bits/stdc++.h>
using namespace std;
#define ll __int64
const int N=320005;
ll phi[10005][105], p2[N], ans[N];
int len, vis[N];
void init(){
len = 0;
for(int i=2; i<N; i++){
if(!vis[i]){
for(int j=i+i; j<N; j+=i) vis[j]=1;
p2[len++] = i;
ans[i] = ans[i-1]+1;
continue;
}
ans[i] = ans[i-1];
}
for(int i=0; i<=10000; i++){
phi[i][0] = (ll)i;
for(int j=1; j<=100; j++){
phi[i][j] = phi[i][j-1] - phi[i/p2[j-1]][j-1];
}
}
}
ll solve_phi(ll m, ll n){
if(!n) return m;
if(p2[n - 1] >= m) return 1;
if(m<=10000 && n<=100) return phi[m][n];
return solve_phi(m, n-1) - solve_phi(m/p2[n-1], n-1);
}
ll solve_p2(ll m){
if(m < (ll)N) return ans[m];
ll y = (int)cbrt(m*1.0);
ll n = ans[y];
ll sum = solve_phi(m, n) + n -1;
for(ll i=n; p2[i]*p2[i]<=m; i++)
sum = sum - solve_p2(m/p2[i])+solve_p2(p2[i])-1;
return sum;
}
int main(){
init();
ll n;
scanf("%I64d", &n);
ll S = cbrt(n*1.0);
S = solve_p2(S);
ll tmp=0;
for(int i=0; i<len; i++){
if(p2[i]*p2[i]>=n) break;
ll x = n/p2[i];
ll s = solve_p2(x);
s-=tmp+1;
tmp = solve_p2(p2[i]);
S+=s;
}
printf("%I64d\n", S);
return 0;
}