Ep 素数概率 , Ek 合数概率 , p 素数期望, k 合数期望 ( 平均)
E = Ep * p + Ep * Ek * ( p + k ) + Ep * Ek * Ek * (p + 2 * k ) + Ep * Ek * Ek * Ek * ( p + 3 * k ) + .......
= Ep * p * ∑ (Ek ^ x) + Ep * k * ∑ (x * Ek ^ x )
= p * Ep / ( 1 - Ek ) + k * Ep * Ek / ( 1 - Ek ) ^ 2
Ek = 1 - Ep
pos n 之前的素数个数
a(n) n 之前素数期望
b(n) n之前合数期望
E = p + k * Ek / Ep = ( a(n) + b (n) ) / pos ;
线性筛先预处理an bn
这个写的挺费空间 仅供参考
#include <bits/stdc++.h>
using namespace std ;
int prime[1271000],primesize,phi[20000001];
bool isprime[20000001];
void getlist(int listsize)
{
memset(phi , 0 , sizeof(phi)) ;
memset(isprime , 1 , sizeof(isprime));
isprime[1]=false;
for(int i=2;i<=listsize;i++)
{
if(isprime[i]) {prime[++primesize]=i ; phi[i] = (int)sqrt(i + 0.0) - 1 ; }
for(int j = 1 ; j <= primesize && i * prime[j] <= listsize ; j ++)
{
isprime[i*prime[j]]=false;
if(! phi[i*prime[j]] )phi[i*prime[j]] = min(i , prime[j]) - 1 ;
if(i % prime[j]==0)break;
}
}
}
const int maxn = 20000000 ;
int a[20000001] ;
int gcd(int m,int n){
if(m==0) return n;
if(n==0) return m;
if(m%2==0&&n%2==0) return 2*gcd(m/2,n/2);
else if(m%2==0) return gcd(m/2,n);
else if(n%2==0) return gcd(m,n/2);
else
return gcd(m<n?m:n,fabs(m-n));
}
int main(){
getlist(maxn) ;
a[1] = phi[1] = 0 ;
for(int i = 2 ; i <= maxn ; i ++ ){
if(isprime[i]){
a[i] = a[i-1] + phi[i] ;
phi[i] = phi[i-1] ;
}else{
a[i] = a[i-1] ;
phi[i] = phi[i-1] + phi[i] ;
}
}
//for(int i = 1 ; i <= 10 ; i ++ ) cout << a[i] << " " << b[i] << endl ;
int T , n ; scanf("%d" , &T) ;
while( T -- ){
scanf("%d" , &n) ;
if(n == 2 || n == 3){ printf("0/1\n") ; continue ;}
int pos = lower_bound(prime , prime + primesize , n ) - prime ;
if(!isprime[n]) pos -- ;
/*double p , k ; double Ep , Ek ;
Ep = pos * 1.0 / (n - 1) ;
Ek = 1.0 - Ep ;
p = a[n] * 1.0 / (pos) ;
k = b[n] * 1.0 / (n - 1 - pos ) ;
//printf("%f %f %f %f\n" , Ep , Ek , p , k ) ;
double ans = p * Ep / (1 - Ek) + k * Ep * Ek / (1 - Ek) /(1 - Ek) ;*/
int son = a[n] + phi[n] ;
int ss = gcd(son , pos) ;
son /= ss , pos /= ss ;
printf("%d/%d\n",son , pos) ;
}
return 0 ;
}