1. 程式人生 > >luoguP1463 [HAOI2007]反素數

luoguP1463 [HAOI2007]反素數

cor 但是 span define lis radius div int 輸出

題目描述

對於任何正整數x,其約數的個數記作g(x)。例如g(1)=1、g(6)=4。

如果某個正整數x滿足:g(x)>g(i) 0<i<x,則稱x為反質數。例如,整數1,2,4,6等都是反質數。

現在給定一個數N,你能求出不超過N的最大的反質數麽?

輸入輸出格式

輸入格式:

一個數N(1<=N<=2,000,000,000)。

輸出格式:

不超過N的最大的反質數。

輸入輸出樣例

輸入樣例#1: 復制
1000
輸出樣例#1: 復制840

思路:一看這道題,不用說這是個數論,作為數學渣渣的我只好去看題解了,發現了這麽有趣的一個規律。x=∏pi^ki
其中p是質數,k是指數,那麽因數的個數就是(k[1]+1)(k[2]+1)…..(k[n]+1)我們知道了這個規律,我們就可以打表搜索了
代碼:
 1 #include<iostream>
 2 #include<cstdio>
 3 #define ll long long
 4 using namespace std;
 5 ll n;
 6 ll maxn,ans;//maxn是更新因數的個數的,ans更新當前的答案 
 7 int p[20]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,51};
8 void dfs(ll m,ll f,ll t,ll pr) 9 { 10 if(t>maxn||(t==maxn)&&m<ans)//當此時的因數大與最優解的約數的個數,或者當他等於最優解,但是m小時,看題目中反素數的性質,更新最大約數,更新答案 11 { 12 ans=m; 13 maxn=t; 14 } 15 ll i=m,j=0,nt=0;//j代表當前的指數,因為指數應該是單調遞減的所以枚舉[j,pr)區間就可以了 16 //i是這個數的大小,nt是因數的個數
17 while(j<pr)//循環結束的條件 18 { 19 j++;//指數增加 20 if(n/i<p[f])break;//如果乘了這個數超過了n就結束。 21 nt=t*(j+1),i*=p[f];//這個數需要乘以這個質數,還有因數的個數改變 22 if(i<=n)dfs(i,f+1,nt,j);//如果這個數還沒有超過,那麽進行下一層dfs 23 } 24 } 25 int main() 26 { 27 cin>>n; 28 dfs(1,1,1,32); 29 cout<<ans; 30 return 0; 31 }

 

luoguP1463 [HAOI2007]反素數