P1463 [HAOI2007]反素数
题目描述
对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。
如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。例如,整数1,2,4,6等都是反质数。
现在给定一个数N,你能求出不超过N的最大的反质数么?
输入输出格式
输入格式:
一个数N(1<=N<=2,000,000,000)。
输出格式:
不超过N的最大的反质数。
输入输出样例
1000
840
Solution:
本题思路实在是巧妙~~!(膜拜比我小的巨佬——老$K$,他的思路让我受益匪浅!)
第一种思路(其实,准确说是第二种,是先搞懂了搜索的思路才自己琢磨的打表):
首先我们讲下暴力打表,由于数据$n\leq 2*10^9$,于是我们可以线下打表,直接暴力模拟,先根据题目可知$1,2,4,6$都是反质数,所以先输出这$4$个数,记当前最大约数个数$mx$为$4$(即$6$的约数个数),然后从$7$枚举到$2*10^9$,每次判断约数个数是否大于$mx$,大于就更新$mx$并输出该数。表搞完后,其实也没多少个,用数组存下来,然后二分答案找第一个比$n$小的就$OK$了(我打表的代码没有输出,也许机房配置太好了很神奇~~)。
贴一下我的暴力打表程序,显然直接打$1$到$2*10^9$的表肯定行不通,我们先打从$1$到$1000000$的来找规律:
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define For(i,a,b) for(ll (i)=(a);(i)<=(b);(i)++)
#define Max(a,b) ((a)>(b)?(a):(b))
using namespace std;
ll p[]={,,,,},mx=;
il bool get(ll x){
ll ans=;
for(ll i=;i*i<=x;i++){
if(x%i==&&x/i!=i)ans+=;
else if(x%i==&&x/i==i)ans++;
}
//cout<<ans<<endl;
if(mx<ans){
mx=ans;
return ;
}
return ;
}
int main(){
freopen("la.out","w",stdout);
For(i,,)if(get(i)){printf("%lld,",i);}
return ;
}
然后对打出来的数:
$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,83160,110880,166320,221760,277200,332640,498960,554400,665280,720720$
进行质因数分解:$$1=1$$
$$2=2^1$$
$$4=2^2$$
$$6=2^1*3^1$$
$$12=2^2*3^1$$
$$24=2^3*3^1$$
$$36=2^2*3^2$$
$$48=2^4*3^1$$
$$60=2^2*3^1*5^1$$
$$120=2^3*3^1*5^1$$
$$180=2^2*3^2*5^1$$
$$240=2^4*3^1*5^1$$
$$360=2^3*3^2*5^1$$
$$720=2^4*3^2*5^1$$
$$840=2^3*3^1*5^1*7^1$$
$$1260=2^2*3^2*5^1*7^1$$
$$1680=2^4*3^1*5^1*7^1$$
$$2520=2^3*3^2*5^1*7^1$$
$$5040=2^4*3^2*5^1*7^1$$
$$7560=2^3*3^3*5^1*7^1$$
$$10080=2^5*3^2*5^1*7^1$$
$$15120=2^4*3^3*5^1*7^1$$
$$20160=2^6*3^2*5^1*7^1$$
$$25200=2^4*3^2*5^2*7^1$$
$$27720=2^3*3^2*5^1*7^1*11^1$$
$$45360=2^4*3^4*5^1*7^1$$
$$50400=2^5*3^2*5^2*7^1$$
$$55440=2^4*3^2*5^1*7^1*11^1$$
$$83160=2^3*3^3*5^1*7^1*11^1$$
$$83160=2^3*3^3*5^1*7^1*11^1$$
$$110880=2^5*3^2*5^1*7^1*11^1$$
$$166320=2^4*3^3*5^1*7^1*11^1$$
$$221760=2^6*3^2*5^1*7^1*11^1$$
$$277200=2^4*3^2*5^2*7^1*11^1$$
$$332640=2^5*3^3*5^1*7^1*11^1$$
$$498960=2^4*3^4*5^1*7^1*11^1$$
$$554400=2^5*3^2*5^2*7^1*11^1$$
$$665280=2^6*3^3*5^1*7^1*11^1$$
$$720720=2^4*3^2*5^1*7^1*11^1*13^1$$
容易发现将质数从小到大排,指数会单调不上升(其实后面老$K$的思路用到了这个性质),那么根据这个东西我们可以线下贪心打表前$12$个质数的幂累乘的形式(幂单调不上升),就能处理出所有的$\leq 2*10^9$的反质数。然后将打表出的数据用数组存下,查询时直接模拟就好了。(打表的代码和下面的搜索代码其实类似,我们可以依次枚举指数保证不上升,然后累乘出的数就是反质数,比较简单就不贴代码了)
贴一个最后的反质数表:
#include<bits/stdc++.h>
using namespace std;
int p[]={,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,};
int main()
{
int n;
cin>>n;
int ans;
for(int i=;;i++)
{
if(p[i]>n) {
cout<<p[i-]<<endl;
return ;
}
}
}
然后讲讲第二种炒鸡玩美的思路:
1、对于一个数$x$,我们根据唯一分解定理,可以将$x$分解为质数的幂相乘的形式:$x=\prod{p_i^{k_i}}$,其中$p_i$为质数。
2、将数$x$唯一分解表示后,则$x$的约数个数$=\prod{(k_i+1)}$(这个证明很简单,$x$的因子是$x$将唯一分解后的质数改变指数相乘得来,质数$p_i$的指数从$0$到$k_i$共$k_i+1$种情况,所以总的约数个数为$k_i+1$的累乘)。
3、我们不妨将$p_i$从小到大排列(即保证$p_i>p_{i-1}$),那么不难发现当$d<f$且$k_d<k_f$时一定不是反质数,证明很简单:
$\because x=\prod{p_i^{k_i}}$且$p_i$单调递增
又$\because d<f,\; k_d<k_f$,$x$的约数个数$sum_x=\prod{(k_i+1)}$
$\therefore $一定可以构造一个数$y$,使得$sum_y=sum_x$,只需交换$p_d,p_f$的指数$k_d,k_f$即可
又$\because p_i$单调递增
$\therefore sum_y<sum_x$,那么$g(x)=g(y)$,而$x>y$,显然$x$不可能为一个反质数。(举栗:$2*3^3<2^3*3$,而它们约数个数均为$8$个,显然$2*3^3$不可能是反质数)
由上面的证明我们得到一个反质数$q$唯一分解后将$p_i$递增排列,对应的指数$k_i$一定单调不上升。
因为前$12$个素数的乘积已经爆$2*10^9$,于是我们处理出前$12$个素数,然后$dfs$搜索枚举各质数的指数,判断$ans$即可。
(具体实现看代码,$ORZ——LK$,被低两个年级的人吊打,好虚啊~)
代码:
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
using namespace std;
const int prime[]={,,,,,,,,,,,,};
ll n,ans,mx;
il void dfs(int nu,int qnu,ll t,ll tot){
if(t>mx||t==mx&&tot<ans)ans=tot,mx=t; //当约数个数t大于当前最大约数个数或者约数个数相等且这个数小于当前答案时,更新答案和约数个数最大值
ll sum=tot,i=,nt=;
while(i<qnu){
i++; //枚举约数个数
if(prime[nu]>n/sum)break; //可行性剪枝,注意直接prime[nu]*sum会爆long long
nt=(i+)*t,tot*=prime[nu]; //nt为新的约数个数,tot为新的数值
if(tot<=n)dfs(nu+,i,nt,tot); //继续递归搜索
}
}
/*nu为当前的素数下标,qnu为指数,t为当前约数个数,tot为当前的值*/
int main(){
cin>>n;
dfs(,,,); //2^30>=1e9
cout<<ans;
return ;
}
P1463 [HAOI2007]反素数的更多相关文章
- Luogu P1463 [HAOI2007]反素数ant:数学 + dfs【反素数】
题目链接:https://www.luogu.org/problemnew/show/P1463 题意: 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4. 如果某个正整数x ...
- 洛谷 P1463 [HAOI2007]反素数
https://www.luogu.org/problemnew/show/P1463 注意到答案就是要求1-n中约数最多的那个数(约数个数相同的取较小的) 根据约数个数的公式,在约数个数相同的情况下 ...
- BZOJ 1053: [HAOI2007]反素数ant dfs
1053: [HAOI2007]反素数ant 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1053 Description 对于任何正整 ...
- bzoj1053: [HAOI2007]反素数ant
51nod有一道类似的题...我至今仍然不会写暴搜!!! #include<cstdio> #include<cstring> #include<iostream> ...
- HAOI2007反素数
1053: [HAOI2007]反素数ant Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1346 Solved: 732[Submit][Sta ...
- 【BZOJ】1053: [HAOI2007]反素数ant
1053: [HAOI2007]反素数ant Description: g(x)表示x的约数个数,反素数:对于任意的i (i < x),均有g(i) < g(x),则x为反素数:现在输入不 ...
- bzoj 1053: [HAOI2007]反素数ant 搜索
1053: [HAOI2007]反素数ant Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1497 Solved: 821[Submit][Sta ...
- BZOJ 1053 [HAOI2007]反素数ant
1053: [HAOI2007]反素数ant Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1948 Solved: 1094[Submit][St ...
- 1053: [HAOI2007]反素数ant
1053: [HAOI2007]反素数ant Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3480 Solved: 2036[Submit][St ...
随机推荐
- 【转】Nginx搭建反向代理服务器过程详解
阅读目录 1.1 反向代理初印象 1.2 反向代理的作用 2.1 Nginx是神马? 2.2 Nginx的应用现状 2.3 Nginx的核心特点 3.1 准备一个ASP.NET网站部署到IIS服务器集 ...
- 2018.6.27 Ajax实现异步刷新
Servlet获取URL地址.在HttpServletRequest类里,有以下六个取URL的函数: getContextPath 取得项目名 getServletPath 取得Servlet名 ge ...
- 2017.12.25 Java中面向对象思想的深刻理解
今日内容介绍 1.面向对象思想 2.类与对象的关系 3.局部变量和成员变量的关系 4.封装思想 5.private,this关键字 6.随机点名器 01面向对象和面向过程的思想 * A: 面向过程与面 ...
- python基础一 day17 初识递归
#递归函数 # 了解什么是递归 : 在函数中调用自身函数 # 最大递归深度默认是997/998 —— 是python从内存角度出发做得限制 # 能看懂递归 # 能知道递归的应用场景 # 初识递归 —— ...
- oracle安装报错[INS-30131]执行安装程序验证所需的初始设置失败(无法访问临时位置)解决方法!
最近在电脑上安装oracle12c,安装时,在执行检查环境步骤时候报错: [INS-30131]执行安装程序验证所需的初始设置失败(无法访问临时位置) 最后在网上搜索解决方法,特记录下,以防以后再用到 ...
- CURLOPT_PROGRESSFUNCTION
Author:李强(李祥祥) Date :2012-12-15 17:26 LIBCURL官方网站都没有说清楚道明白进度函数的参数的作用,这点我感觉文档很片面,经总结如下: size_t CUpl ...
- JS起源
一.初始JavaScript Mosaic是互联网历史上第一个普遍使用和显示图片的浏览器1993年问世. 后来由于商标权转让,原本的开发团队又开发了Netscape Navigetor网景浏览器,也是 ...
- mysql切换数据库提示警告:Reading table information for completion of table and column names
登录数据库后,选择数据库时发现以下提示, mysql> use testReading table information for completion of table and column ...
- Android 性能篇 -- 带你领略Android内存泄漏的前世今生
基础了解 什么是内存泄漏? 内存泄漏是当程序不再使用到的内存时,释放内存失败而产生了无用的内存消耗.内存泄漏并不是指物理上的内存消失,这里的内存泄漏是指由程序分配的内存但是由于程序逻辑错误而导致程序失 ...
- Python的三种基本数据类型
数字 int(整型) long(长整型),python对长整型没有限制,理论上可以无限大.python3后没有long了. float 字符串 加了引号的都是字符串. 单引号和双引号没有约 ...