题目大意:
题目链接:https://www.luogu.org/problemnew/show/P1463
输出
1
1
1到
n
n
n中约数个数最多且尽量小的数。
思路:
如果你很厉害的话可以打出来一个表。
#include<cstdio>
#include <iostream>
using namespace std;
long long a[]={1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,1260,1680,2520,5040,7560,10080,15120,20160,25200,27720,45360,50400,55440,83160,110880,166320,221760,277200,332640,498960,554400,665280,720720,1081080,1441440,2162160,2882880,3603600,4324320,6486480,7207200,8648640,10810800,14414400,17297280,21621600,32432400,36756720,43243200,61261200,73513440,110270160,122522400,147026880,183783600,245044800,294053760,367567200,551350800,698377680,735134400,1102701600,1396755360,2001000000};
int n,ans,i;
int main()
{
scanf("%d",&n);
while (a[i]<n) i++;
printf("%lld\n",a[i-1]);
return 0;
}
正解是
D
P
DP
DP,如果你钻研数据范围的话
D
F
S
DFS
DFS也可以过。
什么是钻研数据范围呢?
首先,约数个数尽量多,那么我们就把这个数拆成
p
r
i
m
e
[
1
]
c
[
1
]
×
p
r
i
m
e
[
2
]
c
[
2
]
×
p
r
i
m
e
[
3
]
c
[
3
]
.
.
.
.
.
.
×
p
r
i
m
e
[
k
]
c
[
k
]
prime[1]^{c[1]}\times prime[2]^{c[2]}\times prime[3]^{c[3]}......\times prime[k]^{c[k]}
prime[1]c[1]×prime[2]c[2]×prime[3]c[3]......×prime[k]c[k]。那么由于
n
≤
2
×
1
0
9
n\leq 2\times 10^9
n≤2×109所以即使所有的
c
[
k
]
=
1
c[k]=1
c[k]=1,那么最大的
p
r
i
m
e
[
i
]
prime[i]
prime[i]也只要到
29
29
29,因为
2
×
3
×
5
×
7
×
11
×
13
×
17
×
19
×
23
×
29
≥
2
×
1
0
9
2\times3\times5\times7\times11\times13\times17\times19\times23\times29\geq2\times 10^9
2×3×5×7×11×13×17×19×23×29≥2×109,所以只要
29
29
29就足够了,换句话说,
k
≤
10
k\leq10
k≤10就行了。
那么来证一下
c
[
i
]
c[i]
c[i]。由于
p
r
i
m
e
[
1
]
32
prime[1]^{32}
prime[1]32(即
2
31
2^{31}
231)
≥
2
×
1
0
9
\geq2\times 10^9
≥2×109,所以
c
[
i
]
c[i]
c[i]肯定不会超过
30
30
30。
那么易证
c
[
1
]
≥
c
[
2
]
≥
c
[
3
]
.
.
.
.
.
.
≥
c
[
k
]
c[1]\geq c[2]\geq c[3]......\geq c[k]
c[1]≥c[2]≥c[3]......≥c[k]才有最优解(具体证法可以参考《算法竞赛进阶指南》),那么
D
F
S
DFS
DFS的范围就缩小了很多,直接爆搜即可。
代码:
#include <cstdio>
#include <iostream>
#define ll long long
using namespace std;
const ll num[]={0,2,3,5,7,11,13,17,19,23,29};
ll ans,a[14][41],maxn;
int n;
void dfs(int x,ll sum,int k,ll s)
{
if (sum>n) return;
if (s>ans||(s==ans&&maxn>sum))
{
ans=s;
maxn=sum;
}
if (x>10) return;
for (int i=0;i<=k;i++)
if (a[x][i]<=n)
dfs(x+1,sum*a[x][i],i,s*(i+1));
else break;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=10;i++)
{
a[i][0]=1;
ll k=1;
for (int j=1;j<=30&&k<=n;j++)
{
a[i][j]=k*num[i];
k*=num[i];
}
}
dfs(1,1,30,1);
cout<<maxn;
return 0;
}