洛谷P1463 反素数()

P1463 [POI2001][HAOI2007] 反素数

100%数据时,N<=2e9,即使使用线性的欧拉筛也会TLE

如此大的数据范围,O(1)的时间复杂度都跑不过,

说明要么打表,要么就需要通过计算直接得出答案,而非一个一个数地判断

通过分析,这道题的要求是找出小于等于N的数中

约数个数最多,并且最小的数,称为“反素数”

每一个数都可以表示成几个素数(可能相同)的乘积

比如6=2*3 12=2*2*3

即一个数n=a1^b1*a2^b2*……*an^bn

( a1<a2<……<an && b1>=b2>=……>=bn )

而这个数的约数个数为几个素数指数各加一的乘积

证明很简单

每个素数指数从0到最大作为其某个约数的约数

每个素数可以有指数加一种选择方式

因此这个数约数个数即为

(b1+1)*(b2+1)*……*(bn+1)

 

其中an不超过31,

因为题目要求约数最多且最小

即MAX(b1+1)*(b2+1)*……*(bn+1)

   MIN=a1^b1*a2^b2*……*an^bn

所以素数不可能放着更小的让它指数为0,去让更大的指数升高,这样一定不是我们要的最优解,pass

所以即使所有素数指数都为1

2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 29 * 31 > 2 * 10^9

即an一定小于31

而b1+b2+……+bn<=30

原因也很简单,当素数只有2指数不为0时,指数和最大

有2^31>2e9

即所有素数指数和一定不超过30

这样,我们得出了反素数具备的几个性质

见下方代码头文件前

 1 //反素数y的性质:
 2 //1.y=a1^n1*a2^n2*...*an^nn
 3 // 其中a为素数,n1>=n2>=...>=nn
 4 //2.约数个数(y)=(n1+1)*(n2+2)*...*(nn+1) 
 5 //3.y的质因数指数总和不超过31
 6 //4.y的质因数最大不超过31 
 7 #include <bits/stdc++.h>
 8 using namespace std;
 9 int n;
10 int prime[15]={0,2,3,5,7,11,13,17,19,23,29,31};
11 //所有素数,方便一一枚举 
12 int most=-1;
13 //most表示最大约数个数 
14 long long ans=-1;
15 //ans表示约数最多的数中最小的(符合反素数定义
16 //十年OI一场空,不开long long见祖宗 
17 void dfs(int x,int l,int m,int up){
18 //x表示当前数字大小
19 //l表示当前枚举到的素数约数的下标
20 //m表示x的约数总个数
21 //up表示上一个素数的指数大小 
22     if(m>most||(m==most&&x<ans)){
23     //要么约数更多,要么约数相同但更小 
24         most=m;
25         ans=x;
26     }
27     long long now=x;
28     int i=0;
29     //i表示此素数指数大小 
30     while(i<=up){
31     //反素数性质1,当前素数指数不大于上一素数指数 
32         i++;
33         if(n/now<prime[l])return ;
34         //保证now不超过n 
35         int k=m*(i+1);
36         //反素数性质2,k表示now的约数个数 
37         now*=prime[l];
38         if(now<=n)dfs(now,l+1,k,i);
39     }
40 }
41 int main(){
42     scanf("%d",&n);
43     dfs(1,1,1,31);
44     printf("%d",ans);
45     return 0;
46 } 

蓝题还是很有意思的

//谁掠夺春秋
//谁在大雨之后
//把旗帜插在最高的楼
//执着信念还有谁有
//有谁能坚守
//摇摇欲坠不停退后
//毁灭即拯救
//夏日掠夺春秋
//结局无法看透
//明知城池已失守
//缠绵往复不肯放手

//——极恶都市

posted @ 2022-09-24 07:58  九州霜  阅读(40)  评论(0编辑  收藏  举报