zoukankan      html  css  js  c++  java
  • P1463 [POI2002][HAOI2007]反素数 题解

    CSDN同步

    原题链接

    简要题意:

    (f_x) 表示 (x) 的因数个数。求 (leq n) 的最大的 (x) 使得 $f_x > f_y (1 leq y < x) $.(即求一个最大的比它小的数因数都多的数)

    本题将作为反素数的模板题。

    其实这就是 反素数 的定义,求反素数。

    算法一

    注意到 (f_x) 是积性函数。所以我们用欧拉筛筛出来。

    然后再暴力判断反素数。

    时间复杂度:(O(n)).

    实际得分:(O( exttt{rp})).(看运气,因为这题没说部分分)

    算法二

    我们只需要求最大的反素数,不用求所有的。

    比方说一个反素数 (n = prod_{i=1}^k {p_i}^{k_i}) 为其标准分解形式,其中 (p_i) 严格递增。

    (n) 的因数个数为 (prod_{i=1}^k (k_i + 1))

    此时必然存在:(k_i) 不严格递减。

    为什么呢?

    比方说 (12 = 2^2 imes 3)(18 = 2 imes 3^2).

    此时两者因数个数相同,所以 (18) 肯定不是反素数。

    也就是说,大的素数个数一定不能超过小的,这样就可以是反素数了。

    那么你会问了,这怎么枚举呢?

    (1) 开始轮流乘上素数(注意剪枝),具体见代码。

    因为 (2 imes 3 imes 5 imes 7 imes 11 imes 13 imes 17 imes 19 imes 23 imes 27 > 2 imes 10^9),所以只要这些素数就够了。

    时间复杂度:(O( ext{wys})).(难以分析,但是应该居于线性和对数之间,和开方差不多但难以证明)

    实际得分:(100pts).

    反素数算法太玄学

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    
    inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
    
    int n;
    int p[20]={0,2,3,5,7,11,13,17,19,23,29};
    ll ans=-1,maxn=-1;
    
    inline void dfs(ll dep,int prime,int now,int zhi) {
    //dep 是当前的数,prime 是当前可以选择的质数编号,now 是因数个数,zhi 是最大幂次
    	if(now>maxn || (now==maxn && dep<ans)) ans=dep,maxn=now; //更新答案
    	int j=0; ll i=dep; while(j<zhi) { //枚举幂次
    		j++; if(n/i<p[prime]) break; //超出 n
    		i*=p[prime]; if(i<=n) 
    		dfs(i,prime+1,now*(j+1),j); //往后枚举
    	}
    }
    
    int main(){
    	n=read();
    	dfs(1,1,1,30);
    	printf("%lld
    ",ans); //答案
    	return 0;
    }
    
    
  • 相关阅读:
    The first appliaction for "Hello World!"
    zone
    learn to study
    深入理解 Angular 2 变化监测和 ngZone
    看看吧
    生命周期钩子
    一个简单的todo
    依赖注入
    @Output()
    @Input
  • 原文地址:https://www.cnblogs.com/bifanwen/p/12605557.html
Copyright © 2011-2022 走看看