zoukankan      html  css  js  c++  java
  • 【洛谷P1463】反素数【DFS】【DP】

    题目大意:

    题目链接:https://www.luogu.org/problemnew/show/P1463
    输出11nn中约数个数最多且尽量小的数。


    思路:

    如果你很厉害的话可以打出来一个表。

    #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;
    }
    
    
    

    正解是DPDP,如果你钻研数据范围的话DFSDFS也可以过。
    什么是钻研数据范围呢?
    首先,约数个数尽量多,那么我们就把这个数拆成prime[1]c[1]×prime[2]c[2]×prime[3]c[3]......×prime[k]c[k]prime[1]^{c[1]}\times prime[2]^{c[2]}\times prime[3]^{c[3]}......\times prime[k]^{c[k]}。那么由于n2×109n\leq 2\times 10^9所以即使所有的c[k]=1c[k]=1,那么最大的prime[i]prime[i]也只要到2929,因为2×3×5×7×11×13×17×19×23×292×1092\times3\times5\times7\times11\times13\times17\times19\times23\times29\geq2\times 10^9,所以只要2929就足够了,换句话说,k10k\leq10就行了。
    那么来证一下c[i]c[i]。由于prime[1]32prime[1]^{32}(即2312^{31}2×109\geq2\times 10^9,所以c[i]c[i]肯定不会超过3030
    那么易证c[1]c[2]c[3]......c[k]c[1]\geq c[2]\geq c[3]......\geq c[k]才有最优解(具体证法可以参考《算法竞赛进阶指南》),那么DFSDFS的范围就缩小了很多,直接爆搜即可。


    代码:

    #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;
    }
    
  • 相关阅读:
    scrapy爬取某网站,模拟登陆过程中遇到的那些坑
    Linux平台安装MongoDB
    Oracle HAVING子句
    oracle查找重复记录-转
    PLSQL存储过程(基础篇)-转
    oracle for update和for update nowait的区别
    Oracle两个数据库互相访问,DBLink使用-转
    中国人素质低的根本原因
    威胁李嘉诚是愚蠢的
    回归农村,这才是我想要的生活
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998623.html
Copyright © 2011-2022 走看看