http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1562
题意:求n以内因子最多的那个数。
思路:范围非常大,不能用普通的求约数个数方法。反素数,就是小于这个数的所有数因子都没他多,那么就转变成求1~n之间的最大反素数。
除此之外,还有一个重要性质:
(3)对于p = 2^t1*3^t2*5^t3*7^t4....,p的因子的个数为(t1+1)*(t2+1)*...*(tn+1)。
根据性质(2)(3),总因子个数转化为求每个因子幂个数的组合,通过对可能的幂的个数穷举来达到模拟所有结果。要想使因子最多,2、3等靠前面的素数的因子肯定较多,越往后越少,然而说是这么说的,少也不代表没有,至少这题说明了要事先准备前16个素数才够(可能要少些,我也懒得去试了),至于是不是和10^16有联系,我不知道怎么算出来的= =。枚举的素数个数上限之所以是54,是因为假如最多全是2的幂,一共要2^54才能满足比10^16大的条件。为了满足条件2,每次dfs的幂上限都是上一层的幂大小。这样就转变成最大54叉的,越往下叉越小的一颗树。
感觉每次描述dfs都相当抽象,咋就自己写不出来呢T T。。
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long ll;
const int N = 5010;
const int INF = 0x3f3f3f3f;
int prime[16] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};
ll Maxcur, Maxcnt, n;//Maxcur代表最大因子个数对应的反素数,Maxcnt代表最大因子个数
void dfs(ll step, ll cur, ll cnt, ll Maxnum)
{
if(step >= 16) return;
if(cnt > Maxcnt)
{
Maxcur = cur;
Maxcnt = cnt;
}
if(cnt==Maxcnt && cur<Maxcur) Maxcur = cur;
ll tmp = cur;//在原先反素数的基础上乘第step个素数
for(int i = 1; i <= Maxnum; i++)//枚举第step个素数的个数
{
tmp*=prime[step];
if(tmp>n) return;
dfs(step+1, tmp, cnt*(i+1), i);//下一个质因子肯定个数要比这个少
}
}
int main()
{
// freopen("in.txt", "r", stdin);
while(~scanf("%lld", &n))
{
dfs(0, 1, 1, 54);
printf("%lld\n", Maxcur);
}
return 0;
}
http://codeforces.com/problemset/problem/27/E
题意:给一个数n,求一个最小正整数,使得它的因子个数为n。
思路:反素数的问题一般有两类,一类是给定n,求最大因子数;另一类是给定因子n,求最小数。本题属于后一类。思路写注释了。
codeforce没打过,注册好麻烦,这题没提交,只是搞出个得数。。
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long ll;
const int N = 5010;
const int INF = 0x3f3f3f3f;
int prime[16] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};
ll ans, n;//ans表示满足约数为n的反素数,通过多次贪心求的最小值
void dfs(ll step, ll cur, ll cnt, ll Maxnum)//cur表示当前因子个数所对应的反素数,cnt表示当前因子个数
{
if(step >= 16) return;
if(cnt==n && cur<ans) ans = cur;//更新最小反素数
ll tmp = cur;//在原先反素数的基础上乘第step个素数
for(int i = 1; i <= Maxnum; i++)//枚举第step个素数的个数
{
tmp*=prime[step];
if(tmp>ans) return;//若乘上这个质因子超过了已知最大反素数,不满足求最小反素数的条件,返回
dfs(step+1, tmp, cnt*(i+1), i);//下一个质因子肯定个数要比这个少,因子个数累乘
}
}
int main()
{
// freopen("in.txt", "r", stdin);
while(~scanf("%lld", &n))
{
ans = INF;
dfs(0, 1, 1, 63);
printf("%lld\n", ans);
}
return 0;
}