題目:
t次詢問,每次給你乙個數n,求在[1,n]內約數個數最多的數的約數個數
1 <= n <= 1000000000000000000(18個0)
參考了大佬的**,自己理解的,還有一部分還沒有搞明白
首先,每乙個正整數都能通過互不相同的素數的次方的積得出,下面是一條公式
設n=p1^k1*p2^k2*……*pn^kn,其中p1,p2,……,pn為互不相同的質數,k1,k2,……,kn為正整數;
所謂的約數就是能被n整除的正整數,我們把其中p1^k1移出來,顯然p1^k1能被n整除,同理的p1^0,p1^1,p1^2一直到p1^k1都能被n整除,那麼單單就p1^k1來說,能被n整除的數就有(k1+1),這個+1是包含p1^0的情況,以此類推,n的全部約數就有 (k1+1)*(k2+2)*……*(kn+1)個,這個結論很重要;
接下來只要列舉小於或者等於n的所有 p1^k1*p2^k2*……*pn^kn的組合,然後進行比較 (k1+1)*(k2+2)*……*(kn+1)的大小,選取最大的那個,就是答案;
#include#include#include#include#include#define ll long long
using namespace std;
int p[20] = , t;
ll n;
int dfs(ll num, int pos, int k, int ans) { //num為當前的數值,pos為當前素數的位置,k為當前素數的個數,ans為當前因子的個數
if (pos>15) return 0;
int ret = ans;
for (int i = 1; i <= k; ++i) {
if (n / p[pos]
自己的理解:**首先先列出了18個素數,在參考了其他大佬的**,發現很多都是列大於或等於16個的素數就行了,這裡我不太明白,感覺不是很夠用,這些列舉的素數是用來列舉上面所說的組合的,這裡用到了dfs來進行計算和比較大小,具體過程是這樣的:
給定乙個限制的素數最大次方數 64 (有些大佬的ac**用了111)
起始的數字num=1,使用的素數為事先列舉的素數陣列p中pos=1的素數,然後是乙個限制的素數最大次方 k = 64 ,起始約數ans=1;
這裡有一點要注意的是,dfs的最終結束條件是 for迴圈裡面的 n/p[pos]**的dfs依次是
第一種組合是 p[1]*p[2]*...*p[15], 所有素數的次方都為1。
第二種是 p[1]^2*p[2]^2*... 次方數最高的是最小的那個素數,後面的素數的次方可能為2也可能為1. 每進入一層dfs就用ret把當前約數個數記錄下來,然後繼續把ans*(i+1)(就是最開始講的(k1+1)*(k2+1)*...) 帶入到下一層dfs中,同時把累乘的數字num和次方限制數 i 帶入下一層,進行到最後一層結束dfs的時候不斷的返回上一層,然後用max來判斷當前這一層ret與下一層的 約數個數的最大值,返回這個最大值然後繼續返回上上層;最終能得出所有小於或者等於n的 p1^k1*p2^k2*……*pn^kn的組合的約數最大值是多少;
在這裡,我還有幾點沒有弄明白,希望有知道的大佬講解一下(十分感謝)
1,**中列舉的素數為19個素數,而且最大的素數是47,在n 為19位數的情況下,真的夠用嗎?
2,為什麼dfs中 pos>15 就返回0,不太明白這個條件中15的意思,有一些大佬的ac**用的是16;
3,在起始的限制次方數k的值為什麼是64,有些ac**用的是111;
牛客網 14 n的約數(數論)
題意 中文,就是求1 n中約數最多的數 思路 根據唯一分解定理,我們可以知道乙個數n a1 p1 a2 p2.的約數個數為 1 p1 1 p2 那麼1 n中約數最多的數我們應該怎麼求呢?根據公式我們可以知道我們讓p1,p2,pn最大就好了,那麼我們現在可以列舉乙個素數,列舉到他的次方大於n的時候,我...
牛客練習賽14 A n的約數
n的約數 時間限制 c c 1秒,其他語言2秒 空間限制 c c 262144k,其他語言524288k 64bit io format lld t次詢問,每次給你乙個數n,求在 1,n 內約數個數最多的數的約數個數 第一行乙個正整數t 之後t行,每行乙個正整數n輸出t行,每行乙個整數,表示答案 根...
牛客練習賽14 A n的約數(詳解)
時間限制 c c 1秒,其他語言2秒 空間限制 c c 262144k,其他語言524288k 64bit io format lld t次詢問,每次給你乙個數n,求在 1,n 內約數個數最多的數的約數個數 第一行乙個正整數t 之後t行,每行乙個正整數n 輸出t行,每行乙個整數,表示答案分析 1 約...