zoukankan      html  css  js  c++  java
  • Project Euler 501 Eight Divisors (数论)

    题目链接:

    https://projecteuler.net/problem=501

    题意:

    (f(n)) be the count of numbers not exceeding (n) with exactly eight divisors.

    就是找少于等于 (n)中只有8个因子的个数。

    You are given (f(100) = 10, f(1000) = 180) and (f(10^6) = 224427).

    Find (f(10^{12}))

    题解:

    我们知道,对于 (n=prod p_i^{a_i}) ,那么,(n)的因子的个数有 (prod (a_i+1))个。

    那么,符合题目条件的只有三种情况。

    (1.p^{7} <= n)

    (2.p^{3} * q <= n)

    (3.p * q * r <= n)'

    其中,(p,q,r)是各自不相等的质数,并且 (p < q < r)

    和这题套路一样。

    http://codeforces.com/problemset/problem/665/F

    Codefores这题代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MAX = 2e6+5;   
    const int M = 7;         
    typedef long long ll;
    vector<int> lp, primes, pi;
    int phi[MAX+1][M+1], sz[M+1];
    
    void factor_sieve()
    {
    	lp.resize(MAX);
    	pi.resize(MAX);
    	lp[1] = 1;
    	pi[0] = pi[1] = 0;
    	for (int i = 2; i < MAX; i++) {
    		if (lp[i] == 0) {
    			lp[i] = i;
    			primes.emplace_back(i);
    		}
    		for (int j = 0; j < primes.size() && primes[j] <= lp[i]; j++) {
    			int x = i * primes[j];
    			if (x >= MAX) break;
    			lp[x] = primes[j];
    		}
    		pi[i] = primes.size();
    	}
    }
    
    void init()
    {
    	factor_sieve();
    	for(int i = 0; i <= MAX; i++) {
    		phi[i][0] = i;
    	}
    	sz[0] = 1;
    	for(int i = 1; i <= M; i++) {
    		sz[i] = primes[i-1]*sz[i-1];
    		for(int j = 1; j <= MAX; j++) {
    			phi[j][i] = phi[j][i-1] - phi[j/primes[i-1]][i-1];
    		}
    	}
    }
    
    int sqrt2(long long x)
    {
    	long long r = sqrt(x - 0.1);
    	while (r*r <= x) ++r;
    	return r - 1;
    }
    
    int cbrt3(long long x)
    {
    
    	long long r = cbrt(x - 0.1);
    	while(r*r*r <= x) ++r;
    	return r - 1;
    }
    
    long long getphi(long long x, int s)
    {
    	if(s == 0)  return x;
    	if(s <= M)
            {
    		return phi[x%sz[s]][s] + (x/sz[s])*phi[sz[s]][s];
    	}
    	if(x <= primes[s-1]*primes[s-1])
           {
    		return pi[x] - s + 1;
    	}
    	if(x <= primes[s-1]*primes[s-1]*primes[s-1] && x < MAX)
            {
    		int sx = pi[sqrt2(x)];
    		long long ans = pi[x] - (sx+s-2)*(sx-s+1)/2;
    		for(int i = s+1; i <= sx; ++i) {
    			ans += pi[x/primes[i-1]];
    		}
    		return ans;
    	}
    	return getphi(x, s-1) - getphi(x/primes[s-1], s-1);
    }
    
    long long getpi(long long x)
    {
    	if(x < MAX)   return pi[x];
    	int cx = cbrt3(x), sx = sqrt2(x);
    	long long ans = getphi(x, pi[cx]) + pi[cx] - 1;
    	for(int i = pi[cx]+1, ed = pi[sx]; i <= ed; i++)
           {
    		ans -= getpi(x/primes[i-1-1]) - i + 1;
    	}
    	return ans;
    }
    
    long long lehmer_pi(long long x)
    {
    	if(x < MAX)   return pi[x];
    	int a = (int)lehmer_pi(sqrt2(sqrt2(x)));
    	int b = (int)lehmer_pi(sqrt2(x));
    	int c = (int)lehmer_pi(cbrt3(x));
    	long long sum = getphi(x, a) + (long long)(b + a - 2) * (b - a + 1) / 2;
    	for (int i = a + 1; i <= b; i++)
           {
    		long long w = x / primes[i-1];
    		sum -= lehmer_pi(w);
    		if (i > c) continue;
    		long long lim = lehmer_pi(sqrt2(w));
    		for (int j = i; j <= lim; j++)
                   {
    			sum -= lehmer_pi(w / primes[j-1]) - (j - 1);
    		}
    	}
    	return sum;
    }
    
    long long power(long long a, long long b)
    {
    	long long x = 1, y = a;
    	while(b)
          {
    		if (b&1)  x = x * y;
    		y = y * y;
    		b >>= 1;
    	}
    	return x;
    }
    void solve(long long n)
    {
      ll ans = 0;
      // case 1: p^3 <= n ,p is a prime
      for(int i = 0; i < (int)primes.size(); i++) {
        if (power(primes[i], 3) <= n) {
          //std::cout << primes[i] << '
    ';
          ans += 1;
        }
        else {
          break;
        }
      }
      //  std::cout << "ans=" <<ans << '
    '<<'
    ';
      // case 2: p*q <= n (p < q)
      // p, q is distinct primes
      ll cnt = 0;
      ll q = 0;
      for(int i = 0; i < (int)primes.size(); i++) //p
      {
        ll x = (ll)primes[i]; // p
        q = n / x; //q
        if(q <= x)continue;
        if(q == 0)continue;
        //std::cout << "p=" << x << '
    ';
        //std::cout << "q=" << q << '
    ';
        cnt = lehmer_pi(q);
        if (q >= primes[i]) {
          cnt -= lehmer_pi(x);
        }
        if (cnt <= 0) break;
        //std::cout << "cnt=" <<cnt << '
    ';
        ans += cnt;
      }
      //  std::cout << "p*q finish!" << '
    ';
    
      std::cout << ans << '
    ';
    }
    int main(int argc, char const *argv[])
    {
      ll n;
      init();
      scanf("%lld", &n);
      solve(n);
      return 0;
    }
    

    PE501代码:

    利用 Lucy_Hedgehog's method. (O(n^{3/4}))。跑10min左右...太慢了..

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 2000010;
    vector<int> mark,prime;
    void init()
    {
        mark.resize(maxn);
        mark[1] = 1;
        for (int i = 2; i < maxn; i++)
        {
    	if (mark[i] == 0)
    	{
    	    mark[i] = i;
    	    prime.emplace_back(i);
    	}
    	for (int j = 0; j < (int)prime.size() && prime[j] <= mark[i]; j++)
    	{
    	   int x = i * prime[j];
    	   if (x >= maxn) break;
    	   mark[x] = prime[j];
    	}
        }
    }
    ll check(ll v, ll n, ll ndr, ll nv) {
        return v >= ndr ? (n / v - 1) : (nv - v);
    }
    ll primenum(ll n) // O(n^(3/4))
    {
      assert(n>=1);
      ll r = (ll)sqrt(n);
      ll ndr = n / r;
      assert(r*r <= n && (r+1)*(r+1) > n);
      ll nv = r + ndr - 1;
      std::vector<ll> S(nv+1);
      std::vector<ll> V(nv+1);
      for(ll i=0;i<r;i++) {
        V[i] = n / (i+1);
      }
      for(ll i=r;i<nv;i++) {
        V[i] = V[i-1] - 1;
      }
      for(ll i = 0;i<nv;i++) {
        S[i] = V[i] - 1; //primes number
      }
      for(ll p=2;p<=r;p++) {
        if(S[nv-p] > S[nv-p+1]) {
          ll sp = S[nv-p+1]; // sum of primes smaller than p
          ll p2 = p*p;
      //    std::cout << "p=" << p << '
    '; // p is prime
          for(ll i=0;i<nv;i++) {
            if(V[i] >= p2) {
              S[i] -= 1LL  * (S[check(V[i] / p, n, ndr, nv)] - sp);
            }
            else break;
          }
        }
      }
      ll ans = S[0];
      return ans;
    }
    
    ll qpower(ll a, ll b)
    {
       ll res = 1;
       while(b)
       {
    	if (b&1)  res = res * a;
    	a = a * a;
    	b >>= 1;
       }
       return res;
    }
    
    void solve(ll n)
    {
    
      ll ans = 0;
      // case 1: p^7 <= n ,p is a prime
      for(int i = 0; i < (int)prime.size(); i++) {
        // for example 2^7 = 128 <=n
        if (qpower(prime[i], 7) <= n) {
          //std::cout << primes[i] << '
    ';
          ans += 1;
        }
        else {
          break;
        }
      }
      std::cout << "p^7 finish!" << '
    ';
    
      // case 2: p^3*q <= n (p < q)
      // p, q is distinct primes
      ll cnt = 0;
      for(int i = 0; i < (int)prime.size(); i++) //p
      {
        ll x = (ll)prime[i]*prime[i]*prime[i]; // p^3
        x = n / x; //q
        if(x == 0)continue;
        cnt = primenum(x);
        if (x >= prime[i]) {
          cnt -= 1;
        }
        if (cnt <= 0) break;
        ans += cnt;
      }
      std::cout << "p^3*q finish!" << '
    ';
    
      //case 3: p*q*r <= n (p < q < r)
      // p,q,r is distinct primes
      for(int i = 0; i < (int)prime.size(); i++) // p
      {
        if (qpower(prime[i], 3) > n) {
          break;
        }
        for(int j = i+1; j < (int)prime.size(); j++) // q
        {
          ll x = n / ((ll)prime[i]*prime[j]);
          if(x <= j)continue;
          if(x == 0)continue;
          cnt = primenum(x); // r
          cnt -= j+1;
          if (cnt <= 0) break;
          ans += cnt;
        }
      }
      std::cout << "p*q*r finish!" << '
    ';
      std::cout << ans << '
    ';
      cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.
    ";
    }
    int main(int argc, char const *argv[])
    {
      /* code */
      init();
      solve(100);
      solve(1000);
      solve(1000000);
      solve(1e12);
      return 0;
    }
    
    

    利用Meisell-Lehmer's method。(O(n^{2/3}))。跑10s..

    #include <bits/stdc++.h>
    using namespace std;
    
    const int MAX = 2e6+5;  
    const int M = 7;      
    
    vector<int> lp, primes, pi;
    int phi[MAX+1][M+1], sz[M+1];
    
    void factor_sieve()
    {
    	lp.resize(MAX);
    	pi.resize(MAX);
    	lp[1] = 1;
    	pi[0] = pi[1] = 0;
    	for (int i = 2; i < MAX; i++) {
    		if (lp[i] == 0) {
    			lp[i] = i;
    			primes.emplace_back(i);
    		}
    		for (int j = 0; j < primes.size() && primes[j] <= lp[i]; j++) {
    			int x = i * primes[j];
    			if (x >= MAX) break;
    			lp[x] = primes[j];
    		}
    		pi[i] = primes.size();
    	}
    }
    
    void init()
    {
    	factor_sieve();
    	for(int i = 0; i <= MAX; i++) {
    		phi[i][0] = i;
    	}
    	sz[0] = 1;
    	for(int i = 1; i <= M; i++) {
    		sz[i] = primes[i-1]*sz[i-1];
    		for(int j = 1; j <= MAX; j++) {
    			phi[j][i] = phi[j][i-1] - phi[j/primes[i-1]][i-1];
    		}
    	}
    }
    
    int sqrt2(long long x)
    {
    	long long r = sqrt(x - 0.1);
    	while (r*r <= x) ++r;
    	return r - 1;
    }
    
    int cbrt3(long long x)
    {
    
    	long long r = cbrt(x - 0.1);
    	while(r*r*r <= x) ++r;
    	return r - 1;
    }
    
    long long getphi(long long x, int s)
    {
    	if(s == 0)  return x;
    	if(s <= M)
      {
    		return phi[x%sz[s]][s] + (x/sz[s])*phi[sz[s]][s];
    	}
    	if(x <= primes[s-1]*primes[s-1])
      {
    		return pi[x] - s + 1;
    	}
    	if(x <= primes[s-1]*primes[s-1]*primes[s-1] && x < MAX)
      {
    		int sx = pi[sqrt2(x)];
    		long long ans = pi[x] - (sx+s-2)*(sx-s+1)/2;
    		for(int i = s+1; i <= sx; ++i) {
    			ans += pi[x/primes[i-1]];
    		}
    		return ans;
    	}
    	return getphi(x, s-1) - getphi(x/primes[s-1], s-1);
    }
    
    long long getpi(long long x)
    {
    	if(x < MAX)   return pi[x];
    	int cx = cbrt3(x), sx = sqrt2(x);
    	long long ans = getphi(x, pi[cx]) + pi[cx] - 1;
    	for(int i = pi[cx]+1, ed = pi[sx]; i <= ed; i++)
      {
    		ans -= getpi(x/primes[i-1-1]) - i + 1;
    	}
    	return ans;
    }
    
    long long lehmer_pi(long long x)
    {
    	if(x < MAX)   return pi[x];
    	int a = (int)lehmer_pi(sqrt2(sqrt2(x)));
    	int b = (int)lehmer_pi(sqrt2(x));
    	int c = (int)lehmer_pi(cbrt3(x));
    	long long sum = getphi(x, a) + (long long)(b + a - 2) * (b - a + 1) / 2;
    	for (int i = a + 1; i <= b; i++)
      	{
    		long long w = x / primes[i-1];
    		sum -= lehmer_pi(w);
    		if (i > c) continue;
    		long long lim = lehmer_pi(sqrt2(w));
    		for (int j = i; j <= lim; j++)
        	{
    			sum -= lehmer_pi(w / primes[j-1]) - (j - 1);
    		}
    	}
    	return sum;
    }
    
    long long power(long long a, long long b)
    {
    	long long x = 1, y = a;
    	while(b)
      {
    		if (b&1)  x = x * y;
    		y = y * y;
    		b >>= 1;
    	}
    	return x;
    }
    void solve(long long n)
    {
      	init();
      	long long ans = 0, val = 0;
    
    	// case : p^7 <= n ,p is a prime
    	for(int i = 0; i < primes.size(); i++) {
            // for example 2^7 = 128 <=n
    		if (power(primes[i], 7) <= n) {
              //std::cout << primes[i] << '
    ';
    			ans += 1;
    		}
    		else {
    			break;
    		}
    	}
        //  std::cout << "ans = " << ans << '
    ';
    
    	// case : p^3*q <= n (assume q > p for finding unique pairs)
           // p, q is distinct primes
    	for(int i = 0; i < primes.size(); i++) //p
      	{
    		long long x = (long long)primes[i]*primes[i]*primes[i]; // p^3
    		x = n / x; //q
    		val = lehmer_pi(x);
    		if (x >= primes[i]) {
    			val -= 1;
    		}
    		if (val <= 0) break;
    		ans += val;
    	}
    	//case : p*q*r <= n (assume r > q > p for finding unique pairs)
            // p,q,r is distinct primes
    	for(int i = 0; i < primes.size(); i++) // p
      	{
    		if (power(primes[i], 3) > n) {
    			break;
    		}
    		for(int j = i+1; j < primes.size(); j++) // q
        	       {
    			long long x = n / ((long long)primes[i]*primes[j]);
          		        if(x < j)continue;
    			val = lehmer_pi(x); // r
    			val -= j+1; // 减去 计算 <=x 的素数个数中多余的
    			if (val <= 0) break;
    			ans += val;
    		}
    	}
    	std::cout << ans << '
    ';
      	cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.
    ";
    }
    int main(int argc, char const *argv[])
    {
      /* code */
      solve(1e12);
      return 0;
    }
    
    
  • 相关阅读:
    JavaScript——引用类型
    react+express+mongodb搭建个人博客
    JavaScript——变量及其作用域
    CSS——盒子模型
    CSS——浮动及清除浮动
    hexo博客分支教训
    使用Node.js+Express 简易开发服务端实例
    发布Nuget包命令
    当心引用类型的“坑”
    sqlcmd相关
  • 原文地址:https://www.cnblogs.com/LzyRapx/p/8453170.html
Copyright © 2011-2022 走看看