反素數 -- 數學

反素數就是區間內約數個數最多的那個數。

在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.pswp.cn/news/373889.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/373889.shtml
英文地址,請注明出處:http://en.pswp.cn/news/373889.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

編程挑戰系統的輸入和輸出詳細說明

在高校俱樂部線上編程挑戰中&#xff0c;一道題目的所有測試數據是放在一個文本文件中&#xff0c;選手將一道題目的程序提交給評判系統運行&#xff0c;程序從該文件中讀取測試數據&#xff0c;再把運行結果輸出到另一個文本文件中。系統把輸出文件與標準答案比對&#xff0c;…

上傳文件---未能找到路徑“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…

使用SPANN方式將Spring&Quartz與自定義注釋集成

在上一篇文章中 &#xff0c;我們演示了如何在Spring容器中創建和配置帶批注的Quartz作業。 我們使用了一個類級別的注釋將一些元數據添加到實現Quartz Job的bean中。 批注定義了作業的名稱&#xff0c;組及其cron表達式。 后來&#xff0c;大部分代碼專用于處理該批注&#xf…

python opencv旋轉_Python opencv實現與rotatedrect類似的矩形旋轉,pythonopencv,RotatedRect

本文原理&#xff1a;先旋轉矩形到指定角度&#xff0c;然后提取矩形外輪廓&#xff0c;從而獲取旋轉后的矩形坐標點。#&#xff01;/usr/bin/env python3# -*- coding: utf-8 -*-# Author: tcy# Date: 2020-5-2 21:00:53# Version:V1.01# Last Modified by: tcy shanghai song…

關于string轉整數

又是leetcode的easy級別題&#xff0c;很基本的題目&#xff0c;卻漏考慮很多情況&#xff0c;動手前一定要考慮清楚呀&#xff01;&#xff01;&#xff01; 就當做鍛煉寫作能力吧&#xff0c;先上題目&#xff01; 將文本轉換成整數&#xff0c;注意一下幾點&#xff1a; 1.文…

數字三角形——遞歸、遞推、記憶化搜索

數字三角形 描述: 有一個由非負整數組成的三角形&#xff0c;第一行只有一個數&#xff0c;除了最下行之外每個數的左下方和右下方各有一個數。 問題&#xff1a; 從第一行的數開始&#xff0c;每次可以往左下或右下走一格&#xff0c;直到走到最下行…

Java 7功能概述

前面我們討論了所有未納入Java 7的內容&#xff0c;然后回顧了將其納入Java 7的有用的Fork / Join框架 。 今天的帖子將帶我們了解Project Coin的每個功能-一系列小的語言增強功能&#xff0c;這些功能雖然不是開創性的&#xff0c;但是對于任何能夠使用JDK 7的開發人員來說都是…

緩存技術

提升系統性能的主要方式之一就是緩存。它可以擋掉大部分的數據庫訪問的沖擊&#xff0c;如果沒有它&#xff0c;系統很可能會因為數據庫不可用導致整個系統崩潰。 但是緩存帶來了另外一些棘手的問題&#xff1a; 數據的一致性和實時性。 例如&#xff0c;數據庫中的數據狀態已經…

水晶報表分組分欄_web報表可視化設計器工具推薦

古往今來&#xff0c;信息就是決勝的關鍵。在科技時代的今天亦是如此。企業的數據管理在幫助企業加強管控、提高競爭力等方面具有不可或缺的作用。這就不得不說到報表工具。企業想要將儲存于各種商業信息系統中的數據轉化成有用的信息&#xff0c;最終幫助決策者做出更快、更好…

嵌套矩形——DAG上的動態規劃

有向無環圖&#xff08;DAG,Directed Acyclic Graph&#xff09;上的動態規劃是學習動態規劃的基礎。很多問題都可以轉化為DAG上的最長路、最短路或路徑計數問題。 題目描述&#xff1a; 有n個矩形&#xff0c;每個矩形可以用兩個整數a,b描述&#xff0c;表示它的長和寬。矩形…

Twisted

Twisted定義Twisted是一個基于事件驅動的網絡引擎框架網絡框架&#xff0c;別人預先定義好的一個框架&#xff08;一個項目&#xff09;&#xff0c;如.net某個web框架有25個class&#xff0c;從BeginRequest依次執行類里的process方法&#xff0c;程序員自己定義一個類&#x…

從Spring到Java EE 6

我最近在一個非常復雜的項目中工作&#xff0c;其中融合了許多Java EE 6技術&#xff08;例如JPA&#xff0c;JAXB&#xff0c;JMS&#xff0c;JTA&#xff0c;JAX-RS等&#xff09;。 出于生產力和計劃方面的原因&#xff0c;將原型應用程序設計為獨立的純Spring應用程序。 當…

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…

MAC itunes無法驗證服務器s.mzstatic/itunes無法更新服務器解決方案

打開host文件&#xff1a; 一、用終端打開&#xff1a; sudo vi /etc/hosts 輸入完這行命令后需要輸入電腦密碼&#xff0c;然后確認&#xff0c;進入host文件 然后按i鍵進入編輯模式&#xff0c;在最后一行添加&#xff1a;23.214.233.166 s.mzstatic.com 如下圖 添加完后&…

硬幣問題——固定終點的最長路和最短路

問題描述&#xff1a; 有n種硬幣&#xff0c;面值分別為V1,V2...,Vn,每種都有無限多。給定非負整數S&#xff0c;可以選用多少個硬幣&#xff0c;使得面值之和恰好為S&#xff1f;輸出硬幣數目的最小值和最大值。0 < n < 100, 0 < S < 10000, 1 < Vi < S。 …

讀取nas_NAS怎么玩?除了存放小姐姐,它竟然還有這些功能

自從有了電腦&#xff0c;就一直在折騰"存儲那點事兒"&#xff0c;說到底&#xff0c;電腦的本質就是存儲&#xff0c;而自己弄家用存儲方面的東西算下來也有幾年了。單機的硬盤存儲比較簡單&#xff0c;但是隨著家里各種設備的增多&#xff0c;各個設備間的文件共享…

ZK Web框架思想

我曾多次被要求提出一些有關ZK的意見。 因此&#xff0c;根據我作為ZK用戶4年的經驗&#xff0c;以下是一些想法&#xff1a; 總體開發人員經驗&#xff0c;社區和文檔 “就是這樣” ZK提供的大多數東西都能很好地工作&#xff0c;并且如果您以前開發過任何桌面Java應用程序&…

OC第一講:類和對象

今天終于開始進行OC的學習了 一.首先講了NSLog NSLog是oc里面的輸出語句&#xff0c;其用法和printf差不多&#xff0c;但是還是有差別的 1&#xff0c;NSLog是自動換行的&#xff0c;不用像printf那樣還需要加\n&#xff1b; 2&#xff0c;NSLog在引號面前需要添加符號&#x…

【轉載】關于 Google Chrome 中的全屏模式和 APP 模式

【來源于】新浪微博&#xff1a;阿博 http://www.cnblogs.com/abel/p/3235839.html 全屏模式&#xff1a;kiosk 默認全屏打開一個網頁呢&#xff0c;只需要在快捷方式中加上 --kiosk [url] 就可以了。 關于全屏模式&#xff1a; 1、全屏模式下&#xff0c;廣告插件&#xff08;…

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…