【搜索】【约数个数定理】[HAOI2007]反素数ant

对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。
如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。


所以,n以内的反质数即为不超过n的约数个数最多的数。

怎样计算约数个数?

约数个数定理:
对于一个大于1正整数n可以分解质因数:n=p1^a1*p2^a2*p3^a3*…*pk^ak,
则n的正约数的个数就是(a1+1)(a2+1)(a3+1)…(ak+1) .
其中a1、a2、a3…ak是p1、p2、p3,…pk的指数。
 
所以,只需枚举一个数的所有质因数就行。
 
最多用到的 不同的 质因数 有多少呢?
 
∵2*3*5*7*11*13*17*19*23*29>2000000000
 
∴最多只用用到这么多不同的质因数。
 
搜索即可。
 
加两个剪枝:
①从小到大枚举质因数,不要让 顺序不同的 算作不同的方案。
 
②小的因数的指数必然大于大的因数的指数,
∵<1>约数个数相同时,小的数更优。
<2>大的数与小的数有相同的因数个数时,根据定义,大的数压根不是反质数了。

Code:
 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 const int prime[]={0,2,3,5,7,11,13,17,19,23,29};
 5 int n,Time[11],sum;
 6 long long ans;
 7 int Calc()
 8 {
 9     int res=1;
10     for(int i=1;i<=10;i++)
11       res*=(Time[i]+1);
12     return res;
13 }
14 void dfs(long long now,int last)
15 {
16     if(now>n)
17       return;
18     int tmp=Calc();
19     if(sum<tmp||(sum==tmp&&now<ans)){sum=tmp;ans=now;}
20     for(int i=1;i<=10;i++)
21       if(Time[i]<Time[i-1]&&i>=last)
22         {
23             Time[i]++;
24             dfs(now*prime[i],i);
25             Time[i]--;
26         }
27 }
28 int main()
29 {
30     scanf("%d",&n);
31     Time[0]=2147483647;
32     dfs(1,0);
33     cout<<ans<<endl;
34     return 0;
35 }
——The Solution By AutSky_JadeK From UESTC 转载请注明出处:http://www.cnblogs.com/autsky-jadek/
原文地址:https://www.cnblogs.com/autsky-jadek/p/3959469.html