反素数 -- 数学

反素数就是区间内约数个数最多的那个数。

在ACM题目里,

一般是求约数最多而且数字最小的那个数,【1--n】

二是求约数刚好等于n的最小的那个数

三是求区间里的最小反素数【beign,end】

1和3有区别吗?有,1可以加速,3只能暴力

先说下思路

思路 : 官方题解 : 

(1)此题最容易想到的是穷举,但是肯定超时。

(2)我们可以知道,计算约数的个数和质因数分解有着很大的联系: 若Q的质因数分解为:Q=p1^k1*p2^k2*…*pm^km(p1…pm为素数,k1…km≥1),则Q有(k1+1)(k2+1)…(km+1)个约数。但是质因数分解的时间复杂度很高,所以也会超时。

(3)通过以上的公式,我们可以“突发奇想”:为何不能把质因数分解的过程反过来呢? 这个算法就是枚举每一个素数。初始时让m=1,然后从最小的素数2开始枚举,枚举因子中包含0个2、1个2、2个2…k个2,直至m*2^k大于区间的上限N。在这个基础上枚举3、5、7……的情况,算出现在已经得到的m的约数个数,同时与原有的记录进行比较和替换。直至所有的情况都被判定过了。 这个算法的优化:如果p1*p2*p3*……*pk>N(pi表示第i个素数),那么只要枚举到p k-1,既不浪费时间,也不会遗漏。

(4)以上的算法还不是最好的,还可以继续优化。 我们看以下的例子: 6=2*3 10=2*5 6和10的质因数分解“模式”完全相同,所以它们的约数个数是相同的。但是由于3<5,所以6<10。 12=2^2*3 18=3^2*2 12和18的质因数分解“模式”完全相同,所以它们的约数个数是相同的。但是由于12的质因数分解中2的指数大于3的指数,18的质因数分解中3的指数大于2的指数,所以12<18。 根据以上的举例,我们也可以对(3)中的算法进行一个改进:可以在枚举时进行一个优化,使得枚举到的数字中2的指数不小于3的指数,3的指数不小于5的指数……这样我们就能够得到质因数分解“模式”相同的最小数(证明略)。再对于每一个得到的数进行比较和记录。这个算法的优化力度极大,效率几乎达到了极限。

 

每个思路都很好理解,所以

http://codeforces.com/problemset/problem/27/E

这是签到题了,约数刚好等于n,那么最需dfs的时候判断即可,用第4这个方法的思路,time 30ms

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
LL pr, mx, BEGIN, END = 1e18;
const int maxn=50+20;
int prime[maxn];//这个记得用int,他保存的是质数,可以不用开maxn那么大
bool check[maxn];
int total;
int n;
void initprime() {for (int i=2; i<=maxn-20; i++) {if (!check[i]) { //是质数了prime[++total]=i;//只能这样记录,因为后面要用
        }for (int j=1; j<=total; j++) { //质数或者合数都进行的if (i*prime[j]>maxn-20) break;check[i*prime[j]]=1;if (i%prime[j]==0) break;//关键,使得它只被最小的质数筛去。例如i等于6的时候。//当时的质数只有2,3,5。6和2结合筛去了12,就break了//18留下等9的时候,9*2=18筛去
        }}return ;
}
void dfs(LL curnum, int cnt, int depth, int up) {if (depth > total) return ; // 越界了,用不到那么多素数if ((cnt > mx || cnt == mx && pr > curnum) && cnt == n) {pr = curnum;mx = cnt;}for (int i = 1; i <= up; ++i) { //枚举有多少个prime[depth]if (END / curnum < prime[depth]) return ;if ((BEGIN - 1) / curnum == END / curnum) return ; //区间不存在这个数的倍数curnum *= prime[depth]; //一路连乘上去dfs(curnum, cnt * (i + 1), depth + 1, i); // 2^2 * 3, 3最多2个
    }
}void work() {cin >> n;dfs(1, 1, 1, 64);cout << pr << endl;return ;
}int main() {
#ifdef localfreopen("data.txt","r",stdin);
#endifinitprime();work();return 0;
}
View Code

http://vjudge.net/problem/11177

求1--n里最小反素数,思路一样

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
LL pr, mx, BEGIN, END;
const int maxn=50+20;
int prime[maxn];
bool check[maxn];
int total;
void initprime() {for (int i=2; i<=maxn-20; i++) {if (!check[i]) { prime[++total]=i;}for (int j=1; j<=total; j++) { if (i*prime[j]>maxn-20) break;check[i*prime[j]]=1;if (i%prime[j]==0) break;}}return ;
}void dfs(LL curnum, int cnt, int depth, int up) {if (depth > total) return ; // if ((cnt > mx || cnt == mx && pr > curnum) && curnum >= BEGIN) {pr = curnum;mx = cnt;}for (int i = 1; i <= up; ++i) { if (END / curnum < prime[depth]) return ;if ((BEGIN - 1) / curnum == END / curnum) return ; //
        curnum *= prime[depth]; //
        dfs(curnum, cnt * (i + 1), depth + 1, i);}
}void work() {pr = 0, mx = 0, BEGIN = 1;cin >> END;dfs(1, 1, 1, 64);cout << pr << " " << mx << endl;return ;
}int main() {
#ifdef localfreopen("data.txt","r",stdin);
#endifinitprime();int t;cin >> t;while (t--) {work();}return 0;
}
View Code

难题是这个

http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1203

求解区间内[begin,end]最小反素数

用4思路啊,不行,为啥,因为4只关心约数个数,没考虑过区间问题,很明显2^2*3  4的思路限制了3的个数最多只能是2,

举个例子[150,150]你怎么破?150 = 2*3*5*5,这种情况,在4中是不可能的,所以只能用3了

 

首先,数据范围是n<=1e9,数据太大,如何快速算出来呢?我们注意到,如果是暴力算的话,最快的方法就是分解质因子,然后组合式计算啦。但是在算18和30的约数的时候,他们的

gcd(18,30)=6,其实是被重复算了的,那么我们思维反过来一下,把分解质因数变成用质因数去组合,使得变成区间内的数,这样一来,我们在2*3的时候,*3就得到了18,*5就得到了30,能省掉一定的时间。但是还是会TLE。假如我们现在枚举到的数是now,会不会它的约数根本就没可能存在于区间里呢?也就是[begin,end]根本就没这些约数。[7,11]内是不会存在6的倍数的。如果[1,begin-1]中6的约数和[1,end]中6的约数相同,说明什么?新加进去的区间[begin,end]根本就没6的约数,这里可以剪枝。还是TLE!!可行性剪枝,如果一个数是now,现在枚举一个新的质数去乘以它,去结合成新的数字,那么如果它无论组成什么其他数字,因子个数都不会超过当前最优值mx呢?怎么判断呢?放缩咯,假如现在是2*3,重新去匹配一个新的素数5,那么,我就要看,当前2*3还能再乘多少个3呢?我记作q,那么这个新的匹配,最理想的情况下因子个数会多2­­q­倍,为什么呢?把那些3,全部替换成5*7*11*13这样来算的话,就是有2q个了。别以为这样没用,当你搜[1,1e9]的时候,你枚举到8000w,再去枚举5那些是没用的,根本就不可能,这里能剪很多。

其实我们还有一个根本的问题没解决,那就是预处理素数到多大,还有万一它是大素数呢?

想着预处理多少,要看数据,预处理出来的最大质数,primeMax‑2是要大过1e9才行的。为什么呢?因为你只有这样,才能防止它数据是两个大质数相乘的形式[primeMax2,primeMax2]。这里的因子个数是3,你枚举不到这个primeMax的话,就只能得到2。

还有那个大素数,没什么怕的,如果当前那个数now,幻想它乘以一个大质数,还是在end的范围的话,就看看*2和mx谁大咯。乘以一个大素数也才加一倍因子数。其实乘以一个小的质因子的话,因子数会更多,这里主要是判断只有一个大素数的特殊情况。枚举不到那个大素数那里的。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
LL pr, mx, BEGIN, END = 1e18;
const int maxn=1e6+20;
int prime[maxn];//这个记得用int,他保存的是质数,可以不用开maxn那么大
bool check[maxn];
int total;
int n;
void initprime() {for (int i=2; i<=maxn-20; i++) {if (!check[i]) { //是质数了prime[++total]=i;//只能这样记录,因为后面要用
        }for (int j=1; j<=total; j++) { //质数或者合数都进行的if (i*prime[j]>maxn-20) break;check[i*prime[j]]=1;if (i%prime[j]==0) break;//关键,使得它只被最小的质数筛去。例如i等于6的时候。//当时的质数只有2,3,5。6和2结合筛去了12,就break了//18留下等9的时候,9*2=18筛去
        }}return ;
}
LL mypow (LL a, LL b) {LL ans = 1;while (b) {if (b & 1) {ans *= a;}a *= a;b >>= 1;}return ans;
}
void dfs (int cur,int cnt,LL now,LL from) {LL t=from*(cnt+1);//现在一共拥有的因子数if (now>=BEGIN && t>mx || t==mx && pr>now && now >= BEGIN) { //有得换了mx=t;pr=now;}for (int i=cur; i<=total; ++i) { //枚举每一个素数LL temp = now*prime[i];if (END / now < prime[i]) return ; //这个数超出范围了if (i == cur) { //没有变,一直都是用这个数.2^kdfs(cur,cnt+1,temp,from);//唯一就是from没变,一直都是用着2,不是新质数} else { //枚举新质数了。LL k = (cnt+1)*from; //现在有K个因子LL q=(LL)(log(END/now) / log(prime[cur])); //2*3插入5时,用的是3来放缩LL add = k*mypow(2,q);if (add < mx) return ; //这里等于mx不return,可以输出minprif ((BEGIN-1)/now == END/now) return; //不存在now的倍数if (END/now > prime[total]) { //试着给他乘上一个大素数 [999991,999991]if ( k*2 > mx ) { //乘以一个大素数,因子数*2pr = END;//如果只有一个大素数[1e9+7,le9+7]那么,就是端点值//否则,是2*3*5*bigprime的话,结果不是最优的,mx = k*2;}}dfs(i,1,temp,k);}}return;
}void work() {cin >> BEGIN >> END;dfs(1,0,1,1);cout << mx << endl;
//    cout << pr << " " << mx << endl;return ;
}int main() {
#ifdef localfreopen("data.txt","r",stdin);
#endifinitprime();work();return 0;
}
View Code

//cur:当前枚举质数的下标,不用返回来枚举了。

//cnt:分解质因式时:拥有(当前下标那个)素数多少个

//now:当前枚举的那个数字,就是所有质因子相乘得到的数子

//from: 假如:2*2*3*5*7,然后枚举3,记录的是2*2,枚举5,记录的是2*2*3,

//如果是枚举相同的数,则不用变,因为它记录的是上一个不同的质因子一共拥有的因子数。

//所以乘上(cnt+1),就是包括上现在这个质因子一共拥有的因子数了。

dfs(1,0,1,1); //刚开始的时候,下标从1开始,拥有这个素数0个,当前数字最少也是1吧

 

转载于:https://www.cnblogs.com/liuweimingcprogram/p/5877411.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/373889.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

上传文件---未能找到路径“D:\MyProject\Files\”的一部分

C# 使用控件FileUpload 上传文件&#xff0c;简单实例&#xff1a; protected void btnUpload_Click(object sender, EventArgs e){string path Server.MapPath("~/Files/");if (fileUpload.HasFile true){string filename fileUpload.FileName.ToLower();fileUpl…

关于string转整数

又是leetcode的easy级别题&#xff0c;很基本的题目&#xff0c;却漏考虑很多情况&#xff0c;动手前一定要考虑清楚呀&#xff01;&#xff01;&#xff01; 就当做锻炼写作能力吧&#xff0c;先上题目&#xff01; 将文本转换成整数&#xff0c;注意一下几点&#xff1a; 1.文…

数字三角形——递归、递推、记忆化搜索

数字三角形 描述: 有一个由非负整数组成的三角形&#xff0c;第一行只有一个数&#xff0c;除了最下行之外每个数的左下方和右下方各有一个数。 问题&#xff1a; 从第一行的数开始&#xff0c;每次可以往左下或右下走一格&#xff0c;直到走到最下行…

水晶报表分组分栏_web报表可视化设计器工具推荐

古往今来&#xff0c;信息就是决胜的关键。在科技时代的今天亦是如此。企业的数据管理在帮助企业加强管控、提高竞争力等方面具有不可或缺的作用。这就不得不说到报表工具。企业想要将储存于各种商业信息系统中的数据转化成有用的信息&#xff0c;最终帮助决策者做出更快、更好…

Twisted

Twisted定义Twisted是一个基于事件驱动的网络引擎框架网络框架&#xff0c;别人预先定义好的一个框架&#xff08;一个项目&#xff09;&#xff0c;如.net某个web框架有25个class&#xff0c;从BeginRequest依次执行类里的process方法&#xff0c;程序员自己定义一个类&#x…

Centos 6.5 搭建php环境(nginx+mariadb+php7)

1.mariaDb vim /etc/yum.repos.d/MariaDB.repo [mariadb] name MariaDB baseurl http://yum.mariadb.org/5.5/centos5-x86 gpgkeyhttps://yum.mariadb.org/RPM-GPG-KEY-MariaDB gpgcheck1#如果服务器已经安装了MariaDB-Galera-server包&#xff0c;你可能需要在安装MariaDB-s…

读取nas_NAS怎么玩?除了存放小姐姐,它竟然还有这些功能

自从有了电脑&#xff0c;就一直在折腾"存储那点事儿"&#xff0c;说到底&#xff0c;电脑的本质就是存储&#xff0c;而自己弄家用存储方面的东西算下来也有几年了。单机的硬盘存储比较简单&#xff0c;但是随着家里各种设备的增多&#xff0c;各个设备间的文件共享…

OC第一讲:类和对象

今天终于开始进行OC的学习了 一.首先讲了NSLog NSLog是oc里面的输出语句&#xff0c;其用法和printf差不多&#xff0c;但是还是有差别的 1&#xff0c;NSLog是自动换行的&#xff0c;不用像printf那样还需要加\n&#xff1b; 2&#xff0c;NSLog在引号面前需要添加符号&#x…

PL/SQL Developer跑在Oracle 64位数据库上初始化错误

安装完Oracle(64位)、PL/SQL Developer后运行PL/SQL出现如下的错误&#xff1a; 网上查资料说&#xff0c;我的PL/SQL Developer与ORACLE不兼容&#xff0c;即PL/SQL不支持64位的ORACLE&#xff0c;因此得下一个32位的ORCALE客户端并配置相应的参数&#xff1a; 解决步骤小记&a…

gis 联合 融合_GIS技术进化 | 我们为何需要跨平台GIS技术体系?

10月30日&#xff0c;超图在2019 GIS 软件技术大会上发布了SuperMap GIS 10i系列产品。SuperMap GIS 10i全面融入人工智能(AI)技术&#xff0c;创新并构建了GIS基础软件“BitCC”五大技术体系&#xff0c;即大数据GIS、人工智能GIS、新一代三维GIS、云原生GIS和跨平台GIS&#…

UVa11925 Generating Premutations

留坑(p.254) 1 #include<cstdio>2 #include<cstring>3 #include<cstdlib>4 #include<algorithm>5 #include<iostream>6 7 using namespace std;8 9 void setIO(const string& s) { 10 freopen((s ".in").c_str(), "r&qu…

ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务

不指定数据库可以正常连接&#xff1a; 指定数据库和使用PL/SQL Developer都出现错误&#xff1a; 在此说明一下我的环境&#xff1a;Oralce装的是64位的在使用PL/SQL Developer时曾出现过初始化错误&#xff0c;解决办法就是下载oracle 32位客户端并相应的配置。 解决方案一&a…

Devoxx 2011印象

Devoxx 2011结束了&#xff0c;它很棒。 最终&#xff0c;在不得不与妻子和孩子度过周末之后&#xff08;上个星期我很少见过&#xff09;&#xff0c;我找到了写下一些东西的时间。 对我来说&#xff0c;这是第六个Devoxx&#xff0c;我的第一个是2006年-那时我还是一个学生&a…

Ubuntu14.04.3,apt-get出现dpkg: error processing package xxx (--configure)和cups-daemon错误的解决方案...

Ubuntu14.04.3&#xff0c;使用apt-get安装软件的时候&#xff0c;报个莫名其妙的错误&#xff1a; dpkg: error processing package xxx (--configure): balabala...Errors were encountered while processing: cups-daemon cups-core-drivers cups E: Sub-process /usr/bin/d…

实验三 类的继承和多态性

实验三 类的继承和多态性 1.(1)编写一个接口ShapePara&#xff0c;要求&#xff1a; 接口中的方法&#xff1a; int getArea()&#xff1a;获得图形的面积。int getCircumference()&#xff1a;获得图形的周长 (2)编写一个圆类Circle&#xff0c;要求&#xff1a;圆类Circle实现…

ORA-01843:无效的月份

Oracle数据库默认情况下&#xff0c;会以DD-MON-YY的形式显示日期&#xff0c;其中DD是天数&#xff0c;MON是月份的前三个字母&#xff08;大写&#xff09;&#xff0c;而YY是年份的最后两位。数据库实际上会为年份存储4位数字&#xff0c;但是默认情况下只会显示最后两位。 …

贪心策略取得最优解的条件_什么是贪心算法?

一、什么是贪心算法贪心算法是指&#xff0c;在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。(局部最优解&#xff0c;而不是整体最优解)贪心算法没有固定的算法框架&#xff0c;算法设计的关键是贪心策略的选择。必须注意的是&#xff0c;贪心算法不是对所有问题…

头部ct能检查出什么_【安全用药】做CT检查时应注意什么?

点击蓝字 关注我们安安徽徽&#xff0c;你知道做CT检查时应注意什么&#xff1f;上腹部CT检查前患者至少禁食6小时、检查前15分钟喝温开水充盈胃部、CT检查时&#xff0c;患者会受到一定量X射线辐射&#xff0c;应避免过度扫描......本期安全用药&#xff0c;大家一起来了解了解…

虚拟机Linux图形界面配置NAT-桥接

点开“虚拟机->设置->桥接模式&#xff08;勾选复制物理网络连接状态&#xff09;->确认” 点击“右上角扇形网络图标->Edit Connections->Wired->选中->Delete->Add->IPv4 Settings->Method(Manual)->Add->输入IP&#xff0c;子网掩码&am…

Java 8状态更新

即将到来的Java SE 8发行版的两大新语言功能是Lambda Expressions和Modularity。 对于这两者&#xff0c;这些天的状态更新已经发布。 我会与您共享链接&#xff0c;因此您可能会在假期中通读它们 Oracle计划在2013年中期发布Java SE 8。 Lambda项目 Lambda项目以及JSR-335希望…