1. 程式人生 > >Lyft Level 5 Challenge 2018 - Elimination Round D

Lyft Level 5 Challenge 2018 - Elimination Round D

題目大意是給你n個數,然後讓你把n個數相乘,求乘積約數的個數,a[i]<=2e18。題目保證每個a[i]的約數在3到5個之間。這個條件很有用,因為一個數的約數最少為2個,1和它本身,所以可能情況只有4種pq,p的平方,p的三次方,p的四次方。後三個直接套就可以,第一個我們需要特殊處理一下,因為這種情況肯定是兩個質數相乘,我們需要先判斷p或q是否在其他a[j]中出現過,如果出現過,我們直接把p和q加上去就行,否則的話我們其實不用知道p和q是多少,我們只知道當前a[i]可以由兩個數相乘得到,我們將陣列中所有的a[i]得數量找到,那麼這種情況的最終結果等於(sum+1)(sum+1)。感覺這題出的很巧妙。

#include<bits/stdc++.h>
using namespace std;
using LL = int64_t;
const LL mod = 998244353;
const int maxn=1e5+5;
map<LL,LL>mp,vis;
LL a[maxn];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int n;cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    LL ans=1;
    for(int i=1;i<=n;i++) {
        if(a[i]==1) continue;
        LL t=sqrtl(sqrtl(a[i]));
        if((t*t*t*t)==a[i]) mp[t]+=4;
        else {
            t=cbrtl(a[i]);
            if((t*t*t)==a[i]) mp[t]+=3;
            else {
                t=sqrtl(a[i]);
                if((t*t)==a[i]) mp[t]+=2;
                else {
                    LL p=-1;
                    for(int j=1;j<=n;j++) {
                        if(a[i]!=a[j]&&__gcd(a[i],a[j])!=1) {
                            p=__gcd(a[i],a[j]);break;
                        }
                    }
                    if(p!=-1) {
                        mp[p]++;
                        mp[a[i]/p]++;
                    }
                    else {
                        LL cnt=0;
                        if(vis.find(a[i])==vis.end()) {
                            for(int j=1;j<=n;j++) {
                                if(a[i]==a[j]) cnt++;
                            }
                            vis[a[i]]=1;
                            ans=ans*(cnt+1)%mod*(cnt+1)%mod;
                        }
                    }
                }
            }
        }
    }
    for(auto it :mp) {
        ans=(ans*(it.second+1))%mod;
    }
    cout<<ans;
    return 0;
}