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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

牛客 - 牛牛的最大兴趣组(思维+数论)

發布時間:2024/4/11 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 牛客 - 牛牛的最大兴趣组(思维+数论) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出 nnn 個數,要求選出最多的數,使得任意兩個數的乘積不能是三次平方數,三次平方數,諸如23=8,33=272^3=8,3^3=2723=8,33=27

題目分析:這個模型和前兩天 cfcfcf 上遇到的一個樣:CodeForces - 1497E2

這個模型的特點就是,假設要使得任意兩個數的乘積不能是 mmm 次平方數的話,當我們將所有的數字中,出現次數為 mmm 的倍數的質因子都篩掉后,剩下的數一定會兩兩匹配。具體到某個質因子來說,假設其出現次數為 xxx,那么其需要和出現次數為 m?xm-xm?x 的數字匹配,其乘積后該質因子的出現次數才能被 mmm 整除

下面就將本模型擴展到 mmm 次平方數來思考如何求解

又因為經過上述的處理后,除了 111 之外,其他的數都有且僅有唯一一個數字與其匹配。也就是對于每個數來說,只有一個數字與其乘積會不滿足條件,所以這兩個數字肯定不能同時出現。既然如此貪心去想的話,保留出現次數較多的那個數字顯然是最優的

到此本題的思路就已經解決了,現在留下來兩個難點需要我們逐個思考:

  • 如何篩掉出現次數為 mmm 倍的質因子
  • 在篩完的數字中,如何快速找到與其對應的那個數字,即滿足兩個數的乘積是 mmm 次平方數
  • 針對第一點,最樸素的做法就是 O(n)O(\sqrt{n})O(n?) 的唯一分解定理了,對于出現次數可以被 mmm 整除的質因子直接舍棄即可,可惜時間復雜度不允許

    然后考慮也比較常用的,預處理出每個數字的最小質因子,然后 O(logn)O(logn)O(logn) 去篩質因子,這種實現時間復雜度可行,但是我們無法預處理到 2e92e92e9 的數據范圍

    其實我們不難發現,并不需要枚舉出所有的質因子然后判斷,我們的目標是為了篩掉所有 mmm 次平方數的數字,換句話說我們可以預處理出 mmm 次平方的數字,然后用這些數字去篩即可,而這樣的 mmm 次平方數,最多有 2e9m\sqrt[m]{2e9}m2e9? 個數字,又因為合數總是可以被分解成質數,所以我們只需要保留質因子即可,這樣有效數字最終約等于 2e9mlogm\frac{\sqrt[m]{2e9}}{logm}logmm2e9??,針對本題而言,當 m=3m=3m=3 的時候,這個數值約等于 200200200

    那么還剩下一個問題,如何找到對應的數字呢,實際上最樸素的做法還是 O(n)O(\sqrt{n})O(n?) 去唯一分解這個數,如果對于某個質因子 ppp,其出現次數是 xxx,那么其對應的那個數字, ppp 的出現次數一定是 m?xm-xm?x

    到此為止,網上的部分題解,都是 O(nn)O(n\sqrt{n})O(nn?) 實現的,因為本題數據水了,所以給放過去了,其實一組很簡單的 hackhackhack 樣例就是, nnn1e9+71e9+71e9+7,直接就把復雜度卡成至少 1e5?1e4=1e91e5*1e4=1e91e5?1e4=1e9 起步了

    所以該如何去查找對應的那個數字呢,假設我們要找 xxx 對應的數字,只需要將 xxx 變成 xm?1x^{m-1}xm?1,然后再將出現次數為 mmm 的質因子篩掉即可,具體原理就是:對于任意兩個相鄰的自然數來說,都是互質的,所以 gcd(m?1,m)=1gcd(m-1,m)=1gcd(m?1,m)=1,對于公式 a+a?(m?1)=a?ma+a*(m-1)=a*ma+a?(m?1)=a?m,兩邊同時對 mmm 取模得到 a+a?(m?1)=0∣ma+a*(m-1)=0|ma+a?(m?1)=0m,所以將 xxx 變為 xm?1x^{m-1}xm?1 然后再將出現次數為 mmm 的倍數的質因子篩掉就可以找到對應的數字了

    總的時間復雜度就是 O(n2e9m)O(n\sqrt[m]{2e9})O(nm2e9?),對于本題而言就是 O(200?n)O(200*n)O(200?n),實現的時候我套了個 mapmapmap ,理論上說應該是不可以的,但因為本題數據水,所以是可以過的,如果是正解的話我感覺需要打個哈希降一下復雜度,大概就是 unordered_map 了

    代碼:

    // Problem: 牛牛的最大興趣組 // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/7604/C // Memory Limit: 524288 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #define lowbit(x) x&-x using namespace std; typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=1e6+100; bool vis[N]; vector<int>pri; map<LL,int>mp; void init() {for(int i=2;i<=2000;i++) {if(vis[i]) {continue;}for(int j=i+i;j<=2000;j+=i) {vis[j]=true;}}for(int i=2;1LL*i*i*i<=2e9;i++) {if(!vis[i]) {pri.push_back(i*i*i);}} } LL change(LL x) {for(auto it:pri) {while(x%it==0) {x/=it;}}return x; } int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);init();int n;read(n);for(int i=1;i<=n;i++) {LL x;read(x);mp[change(x)]++;}int ans=0;for(auto &it:mp) {if(it.first==1) {ans++;continue;}LL rk=change(it.first*it.first);if(!mp.count(rk)) {ans+=it.second;} else {ans+=max(it.second,mp[rk]);it.second=mp[rk]=0;}}cout<<ans<<endl;return 0; }

    總結

    以上是生活随笔為你收集整理的牛客 - 牛牛的最大兴趣组(思维+数论)的全部內容,希望文章能夠幫你解決所遇到的問題。

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