1. 程式人生 > >最多約數相關問題

最多約數相關問題

申明:思路參考該blog

吐槽:上古時期的資料時真的有毒,注意有一個點錯了;網上各路神仙的解法有點不靠譜,各種暴力加上玄學的騙分(姑且是吧,欺負資料水)都能過也是服了。於是自己上網慢慢找了一下,正確解法。

由於資料較水,演算法方面可能會有些 B u g Bug ,望大佬指點。


文章目錄


知識點:算術基本定理及推論、質數篩選、搜尋

算術基本定理推論
N =

p 1 c 1 p 2 c 2
p m c m N = p_1^{c_1}p_2^{c_2} \cdots p_m^{c_m} ( p p 為質數),則 N N 的正約數個數為 ( c 1 + 1 ) × ( c 2 + 1 ) × ( c m + 1 ) (c_1 + 1) \times (c_2 + 1) \times \cdots (c_m + 1)

T1

題意

正整數 x x 的約數是能整除 x x 的正整數。
正整數 x x 的約數個數記為 d i v ( x ) div(x) 。例如 1 , 2 , 5 , 10 1, 2, 5, 10 都是正整數 10 10 的約數,則 d i v ( 10 ) = 4 div(10)=4 。設 a a b b 2 2 個正整數, a b 2 × 1 0 9 a\leq b \leq 2 \times 10^9 (然而,實際只有 1 0 9 10^9 ),找出 a a b b 之間約數個數最多的數 x x ,求 d i v ( x ) div(x)

分析

有點類似反素數
由於資料範圍實在時太大了,一個一個判段是不可能的。對此,可以考慮直接列舉 p i p_i c i c_i (用dfs實現就好了)。

  • Q : Q: 就算是隻要列舉質數,但 1 0 9 10^9 內的質數也不少。
    A : A: 分解質因數的時候也應該知道,大於 n \sqrt n 的質數其實只有一個,因此,我們只需要列舉 1 0 9 31623 \sqrt {10^9}\approx 31623 內的質數即可。
    a d d : add: 處理大於 n \sqrt n 的質數:當你 d f s dfs 列舉完質數後,若當前的數乘上 n \sqrt n 內最大的質數依舊滿足到達不了 [ l , r ] [l, r] ,則必定存在一個大質數使之滿足條件,對此只需要將原來的約數個數乘上 2 2 即可。(個人感覺,要配合下面的剪枝來減掉一些不存在的情況)
    證:在滿足可行性的情況下,一個包含大質數的整數必定含有 [ 1 , n ] [1, \sqrt n] 中的至少一個約數。
  • 關鍵-可行性剪()枝
  1. 對於區間的約束:若當前的數 n o w now 要成為變成區間 [ l , r ] [l,r] 中某一個數的倍數,則必須要保證 l 1 n o w < r n o w \frac{l - 1}{now} < \frac{r}{now}
  2. 對於答案的約束:若當前要列舉質數 p i p_i ,且當前的數為 n o w now ,約數個數為 s s 。最多還會有 x = log p i r n o w x = \log_{p_i}\frac{r}{now} 個因子,這些因子最多能組成的約數個數為 2 x 2^x 。若 s + 2 x s + 2^x 依舊小於最優答案,那就可以直接剪掉了。(很強力的剪枝,去掉直接 T T

程式碼

注意:刪掉質數表,太卡了

#include <cstdio>
#include <cstdlib>
#include <algorithm>

#define IL inline
#define open(s) freopen(s".in", "r", stdin); freopen(s".out", "w", stdout);
#define close fclose(stdin); fclose(stdout);

using namespace std;

IL int read()
{
	int sum = 0, k= 1;
	char c = getchar();
	
	for(;'0' > c || c > '9'; c = getchar())
	if(c == '-') k = 0;
	
	for(;'0' <= c && c <= '9'; c = getchar())
		sum = sum * 10 + c - '0';
	return k ? sum : -sum;
}

typedef long long ll;

int prime[4648] = {};//刪掉了,否則卡死去
ll L, R;
ll ans;

IL ll get_log(ll x, int p)
{
	ll t = -1;
	for(; x; x/= p, ++t);
	return t;
}

IL void dfs(int t, ll now, ll s)
{
	if(((L - 1) / now) >= (R / now)) return ; //剪枝1
	if(t == 4648)
	{
		if(now * prime[4648 - 1] < L)
		{
			s <<= 1;
			if(s > ans) ans = s; 
		}
		return ;
	}
	if((1 << get_log(R / now, prime[t])) * s  <= ans) return ; //剪枝2
	if(s 
            
           

相關推薦

約數相關問題

申明:思路參考該blog 吐槽:上古時期的資料時真的有毒,注意有一個點錯了;網上各路神仙的解法有點不靠譜,各種暴力加上玄學的騙分(姑且是吧,欺負資料水)都能過也是服了。於是自己上網慢慢找了一下,正確解法。 由於資料較水,演算法方面可能會有些

1-3:約數問題

最多約數問題。正整數x 的約數是能整除x的正整數,其約數的個數記為div(x),例如div(10)=4。設a 和b 是兩個正整數,找出a 和b 之間約數個數最多的數x 的約數個數。     樣例輸入:   1 36 樣例輸出:  

【演算法】約數問題

最多約數問題 題目描述 正整數x的約數是能整除x的正整數。正整數x的約數個數記為div(x)。例如,1,2,5,10都是正整數10的約數,且div(10)=4。 對於給定的2個正整數a<=b,程式設計計算a與b之間約數個數最多的數。 輸入 輸入的第1行有兩個正整數a和

約數問題

問題 最多約數問題:正整數x的約數是能整除x的正整數。正整數x 的約數個數記為div(x)。例如,1,2,5,10 都是正整數10 的約數,且div(10)=4。設a 和b 是2 個正整數,a≤b,找出a和b之間約數個數最多的數x及其最多約數個數。 方法

計算機演算法設計與分析課本(王曉東著)課後演算法實現題1-3 約數問題

問題描述: 正整數x的約數是能整除x的正整數。正整數x的約數個數記為div(x)。例如,1 2 5 10都是10的約數,且div(10)=4。設a和b是2個正整數,a<=b,找出a和b之間約數個數最多的數x。 演算法設計: 對於給定的2個正整數a<=b,計算a和b之間約數個數最多

短路徑相關的問題

one 實現 路徑問題 拓撲 使用 基本 -1 沒有 結構 -------------------siwuxie095 更多和最短路徑相關的問題 在《算法導論》中,關於 Dijkstra 算

小公倍數/大公約數高效演算法模板)

最小公倍數和最大公約數            兩數最小公倍數    輾轉相除法求最大公約數,使a>b,a,b不斷取餘數直到a,b相等 int gcd(int a, int b) { if(a < b) a = a^b, b = b^a, a = a^

【小程式社群】小程式社群提供微信小程式和支付寶小程式相關的資訊、開發教程、開發指南、小程式DEMO等資源。小程式開發社群是國內微信小程式和支付寶小程式開發的領先社群,這裡有最新的功能、全的DEMO、最多的教程和

小程式社群 小程式社群提供微信小程式和支付寶小程式相關的資訊、開發教程、開發指南、小程式DEMO等資源。小程式開發社群是國內微信小程式和支付寶小程式開發的領先社群,這裡有最新的功能、最全的DEMO、最多的教程和最...

約數(divisor)

題目簡述: 求1~N 的數中因子是最多的數 Sample Input 100 Sample Output 60 Data Constraint Hint 有30%的資料,n不超過1000。 有50%的資料,n不超過1000000。 有100

請編寫相關函式來完成對一段英文字串進行字母統計功能,出現那個字母的出現次數,不區分大小寫。

思路:1、對字串進行過濾,把英文字母過濾出來。2、將所有英文字母統一轉成小寫(大寫)。3、將待求的字串與26個字母進行比較並統計個數4、統計出現最多的字母。原始碼:#include <stdio.h>#include <stdlib.h>#includ

python(dict字典相關知識以及小例子:生成一個列表,存放100個隨機整數,找出出現次數的數字)

一、什麼是字典? #字典的使用 #子字典是一個容器類,可以用來儲存資料 #列表儲存資料特點:1、有序的 2、每一個都有一個索引,通過索引可以對資料進行查詢,修改,刪除 #字典儲存資料: key:v

大公約數小公倍數

描述 出現 mage 最大公約數 images code ger return ges 一、問題描述 從鍵盤輸入兩個正整數a和b,求其最大公約數和最小公倍數。 二、算法思想及代碼 求最小公倍數算法:最小公倍數=兩整數的乘積÷最大公約數 求最大公約數算法: (1)輾轉相除法

數組中出現的數,以及接口 Map.Entry<K,V>

int try tools pub length rem value contains span 1 package test.tools; 2 3 import java.util.Collection; 4 import java.util.Collecti

nginx rewrite正則子組匹配到$9

spl html splay erb ice line display and 需要 nginx rewrite正則匹配()匹配子組最多匹配到$9,就是從$0到$9 當需要匹配更多子組時,可通過變量來實現 if ($uri ~ ^/forum-15/sortid-74/(.

尋找出現次數的id

exti 出現 出現次數 util nbsp for pack 次數 題目 題目要求: 論壇中有一個id評論過於頻繁,其出現次數占到3/4,如今簡單編程尋找此id。 設計思想:

【51NOD-0】1011 大公約數GCD

style lose gif lap blog %d 51nod ret display 【算法】歐幾裏德算法 #include<cstdio> int gcd(int a,int b) {return b==0?a:gcd(b,a%b);} int mai

oj-ccf-csp-201312-1-出現次數的數

str nbsp index name std print space {} include #include<cstdio> #include<algorithm> using namespace std; const int maxn

求數組中反復次數的元素

down add 時間復雜度 空間 append 鍵值對 Language trac mod 1.問題描寫敘述   比如:數組a={2,3,1,5,5,5,5,7,8,1}。元素2、3、7、8各出現1次。1出現兩次。5出現4次,則反復次數最多的元素為5

求一個字符串中連續出現次數的子串

article 規律 生成 clu 一次 strong tor first sub 題目:求一個字符串中連續出現的次數最多的子串。 例如,字符串“abababc”,最多連續出現的為ab,連續出現三次。 思路: 例如字符串“abababc”,最多連續出現的為ab,連續出現

40.@返回字符串中出現次數的那個字符和次數2

script 最大 spl 技術分享 char 獲取 code java log 1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="U