【洛谷P1463】反素数【DFS】【DP】

题目大意:

题目链接: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 n2×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×292×109,所以只要 29 29 29就足够了,换句话说, k ≤ 10 k\leq10 k10就行了。
那么来证一下 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值