聰明的燕姿(數論)

2021-10-16 13:21:31 字數 3535 閱讀 1178

【題目背景】

陰天傍晚車窗外

未來有乙個人在等待

向左向右向前看

愛要拐幾個彎才來

我遇見誰會有怎樣的對白

我等的人他在多遠的未來

我聽見風來自地鐵和人海

我排著隊拿著愛的號碼牌

【題目描述】

城市中人們總是拿著號碼牌,不停尋找,不斷匹配,可是誰也不知道自己等的那個人是誰。

可是燕姿不一樣,燕姿知道自己等的人是誰,因為燕姿數學學得好!燕姿發現了乙個神奇的演算法:假設自己的號碼牌上寫著數字 s,那麼自己等的人手上的號碼牌數字的所有正約數之和必定等於 s。

所以燕姿總是拿著號碼牌在地鐵和人海找數字(喂!這樣真的靠譜嗎)可是她忙著唱《綠光》,想拜託你寫乙個程式能夠快速地找到所有自己等的人。

輸入格式:

輸入包含k

組資料。對於每組資料,輸入包含乙個號碼牌s。

輸出格式:

對於每組資料,輸出有兩行,第一行包含乙個整數m,表示有m個等的人。

第二行包含相應的m

個數,表示所有等的人的號碼牌。

注意:你輸出的號碼牌必須按照公升序排列。

【input】

42
【output】

3

2026

41

【分析】

首先這題要用到幾個數論裡的定理,當我第一眼看這些定理的時候,我是很懵逼的。先給出定理的公式。

首先,這裡要用到

1.惟一分解定理:

2.約數和定理 :

首先惟一分解定理:每個大於1的自然數n均可分解為有限個素數之積,就比如

【input】

12
【output】

223

1

下面是**實現

通俗一點就是一下:約數和定理:

比如 20 = 22 +51 (惟一分解定理)

20的所有正約數的和為

(20 +21 +22) *(50+ 51)=42

而這裡的42就是題目中號碼牌s,20是自己等的人手上的號碼牌數字,那這樣子這題就懂啦。

那麼我們可以通過列舉ai和pi來求出m從而得到n,具體的話只要乙個括號內的總和能被m整除那麼ai,pi合法,然而這樣需要算出2*109以內的質數。但是注意到p>=2,那麼就只需要求出根號範圍內的質數即可,注意處理m-1的特殊情況。

這裡先介紹一下線性篩質數(其實相當於我自己在學習)

線性篩:o(n)

1.線性篩的思想就是用最小的質因子把他篩掉

2.從小到大列舉,所以當前的大於,以後的一定大於

3.其實就是埃氏篩的公升級版

int pr[n],v[n]

;//v[i]是i的最小質因子 ,pr[n]是用來存質數的陣列

void

prime()

for(

int j=

1;j<=m;j++

)//列舉所有質數

v[i*pr[j]

]=pr[j]

;//i%pr[j]=0 ->pr[j]是i的最小質因子 ,pr[j]就是咱們的i*pr[j]最小質因子也一定是 pr[j]

}//!=0-> pr[j]不是i的最小質因子, 從小到大列舉,i的最小質因子一定是大於 pr[j]

// pr[j]的最小質因子是pr[j]

//i*pr[j]的最小質因子就是pr[j]

//i * prime[ j ]也就是質數prime[ j ]作為最小質因子能夠篩掉的部分合數

}}

下面上這題的**:

#include

using

namespace std;

#define n 1000100

int pr[n]

,ans[n]

, v[n]

;//v[i]是i的最小質因子 ,pr[n]是用來存質數的陣列

int cnt,m;

void

prime()

for(

int j=

1;j<=m;j++

)//列舉所有質數

v[i*pr[j]

]=pr[j]

;//i%pr[j]=0 ->pr[j]是i的最小質因子 ,pr[j]就是咱們的i*pr[j]最小質因子也一定是 pr[j]

}//!=0-> pr[j]不是i的最小質因子, 從小到大列舉,i的最小質因子一定是大於 pr[j]

// pr[j]的最小質因子是pr[j]

//i*pr[j]的最小質因子就是pr[j]

//i * prime[ j ]也就是質數prime[ j ]作為最小質因子能夠篩掉的部分合數}}

bool

check

(int x)

//判斷是否是素數

for(

int i =

2; i*i <= x; i++

)return1;

}//上乙個質數的下標,拼湊出來的結果,nowleft剩下的成分

void

dfs(

int nowleft,

int product,

int sum1)

//nowleft是拆分後剩餘的部分,product是前面的質數的積

//sum1就是約數和(形如pow(p1,a1)*pow(p2,a2)*...這樣的式子)

//保證now-1至少是2if(

check

(nowleft-1)

&&nowleft-

1>pr[product]

) ans[

++cnt]

= sum1*

(nowleft-1)

;//這是只含乙個的大於sqrt(num)的質數

//降低時間複雜度,防爆int

for(

int i = product+

1; pr[i]

*pr[i]

<=nowleft; i++)}

return;}

intmain()

return0;

}

2017 9 11 聰明的燕姿 失敗總結

這題有毒 如假包換的爆搜 只要知道乙個數的約數加起來 分解質因數後每個 質因數1 pi次字首和 相乘的結果 就好 做 sou 了 所以如果知道約數和,就可以列舉質因數來爆搜 必須剪枝到極致才能過,不然會t 由於約數和 一堆數的乘積,所以有乙個剪枝是只有能整除才去搜 由於分解的質因數不能重,所以遞迴剩...

acWing 1296 聰明的燕姿

用到了算數基本定理的思想,尤拉篩的不記錄最小質因子的板子,另外在優化dfs的時候還用到了小學生求素數的一點小思想,下面我們簡單說一下思路和分析幾個問題。思路 正約數之和等於s的數,容易想到直接列舉每乙個質數與每乙個質數的數量,然後進行優化。第乙個問題 尤拉篩存質數的陣列到底開多大?這個問題,誰一開始...

聰明的燕姿 JLOI2014

陰天傍晚車窗外 未來有乙個人在等待 向左向右向前看 愛要拐幾個彎才來 我遇見誰會有怎樣的對白 我等的人他在多遠的未來 我聽見風來自地鐵和人海 我排著隊拿著愛的號碼牌 城市中人們總是拿著號碼牌,不停尋找,不斷匹配,可是誰也不知道自己等的那個人是誰。可是燕姿不一樣,燕姿知道自己等的人是誰,因為燕姿數學學...