日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ 1053 [HAOI2007]反素数ant

發布時間:2024/4/15 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ 1053 [HAOI2007]反素数ant 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

53: [HAOI2007]反素數ant

Description

  對于任何正整數x,其約數的個數記作g(x)。例如g(1)=1、g(6)=4。如果某個正整數x滿足:g(x)>g(i) 0<i<x,則稱x為反質數。例如,整數1,2,4,6等都是反質數。現在給定一個數N,你能求出不超過N的最大的反質數么

Input

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

Output

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

Sample Input

1000

Sample Output

840
  當我見到這道題的時候是很開心的,這不就是在東北育才當時我打表過70分的divisorful數嗎?細細一想,會發現:   一個合法的divisorful數x要求:0<i<x間存在至多一個數,其約數個數比x多。   ?而一個合法的反質數x要求:0<i<x間不存在任何一個數,其約數個數比x多。   我們可以想,對于一個divisorful數,一定是小因子占先。   例如,6=2*3,約數個數為4。然而,437=19*23,也是4個。很明顯不是。   而這種題,如果打表,會發現整個divisorful數集其實極其稀疏。那么,我們就可以逐步加入各質因數p,讓原divisorful數集中的數*p,*p^2,*p^3,*p^4……直到查詢的邊界。然后將其排序,去掉不合法的數。如果數集沒有變化,就結束了。   我們總結一下,這樣的題滿足:
  • 可以使用數集表示,數集本身較稀疏
  • 可以按合理的順序逐步加入元素,并可貪心化break
  • 加入新元素時可以較快建立其維護信息
  啊啊啊啊啊!這樣可以很快的求出2000000000內的所有反質數。掛個代碼吧: 1 /************************************************************** 2 Problem: 1053 3 User: Doggu 4 Language: C++ 5 Result: Accepted 6 Time:40 ms 7 Memory:852 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 #include <vector> 13 const long long MAX = 2500000000ll; 14 typedef std::vector< std::pair<long long,int> > SET; 15 SET v, w; 16 int p, i, j, k; 17 SET expand(SET &v,int p) { 18 SET w=v; 19 for( i = 0; i < v.size(); i++ ) { 20 long long x=v[i].first*p; 21 for( j = 1; x < MAX; x*=p,j++ ) w.push_back(std::make_pair(x,v[i].second*(j+1))); 22 } 23 sort(w.begin(),w.end()); 24 SET ans; 25 int mx=-1; 26 for( i = 0; i < w.size(); i++ ) { 27 int c=w[i].second; 28 if(c<=mx) continue; 29 ans.push_back(w[i]); 30 mx=w[i].second; 31 } 32 return ans; 33 } 34 int main() { 35 v.push_back(std::make_pair(1,1)); 36 for( p = 2; ; p++ ) { 37 bool pri=1; 38 for( i = 2; i * i <= p; i++ ) if(p%i==0) {pri=0;break;} 39 if(!pri) continue; 40 w=expand(v,p); 41 if(w==v) break; 42 v=w; 43 } 44 scanf("%lld",&k); 45 for( i = 0; i < v.size(); i++ ) if(v[i].first<=k&&v[i+1].first>k) {printf("%lld\n",v[i].first);break;} 46 return 0; 47 } 數集公理化構造

  然而,我發現其他人根本沒有這樣想……

  hzwer如是說:

  本題似乎要先知道許多結論,不要問我證明。。

  一個數約數個數=所有素因子的次數+1的乘積

  舉個例子就是48 = 2 ^ 4 * 3 ^ 1,所以它有(4 + 1) * (1 + 1) = 10個約數

  然后可以通過計算得一個2000000000以內的數字不會有超過12個素因子

  并且小素因子多一定比大素因子多要優

  預處理出前12個素數直接爆搜即可

  霎時間感覺自己被打臉。所謂的結論是:不超過N的最大的反質數是1~N間約數最多且相對最小的值x。很明顯,這樣的數x是一個反質數。若1~N間存在著更大的反質數,則顯然月數個數比x多,與x約數最多矛盾。

  于是只需找1~N間約數最多且相對最小的值x,暴搜居然效率也很高。

  但是,暴搜和我的方法時間差不多,而我卻算出了所有的反質數。若要打表,顯然更優。 

轉載于:https://www.cnblogs.com/Doggu/p/bzoj1053.html

總結

以上是生活随笔為你收集整理的BZOJ 1053 [HAOI2007]反素数ant的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。