[CF1033D]Divisors:约数个数定理

分析:

不要在意那奇怪的分类,那是我实在不知道该往哪类分了。
比赛时一看到这道题想都没想直接写了Pollard-Rho分解质因数搞,然后秒T。
加了个当分解出4个质因子后return的剪枝后,还是T。
然后?然后就没有然后了。
说一下这道题给的官方正解。
首先因为ai约数个数为3~5的限制,所以每个ai都可以写成pq,p^2,p^3,p^4(p,q均为素数且p!=q)中的一种。
我们很容易给后三种形式的ai分解质因数(O(1)或O(logai))。
那么第一种?
枚举每个属于第一种的数ai,然后枚举每一个数(不一定是第一种)aj,当ai!=aj时,令g=gcd(ai,aj)。
如果g!=1,那么我们找到了ai的一个质因子g,自然的也就知道了另一个质因子ai/g。
但是还有一些属于第一种的数还没被分解啊怎么办急死了(//O^O)//TT。
其实我们可以发现,当进行完以上两个步骤后,每个没有被分解的数是与其他所有数互质的(也有可能有和它相同的数,这个需要特殊处理),这样的ai只会给最终的乘积a贡献两个指数为1的质因子,所以可以直接累计入答案。
出题人还说了Pollard-Rho其实很慢,很开心Pollard-Rho过不了233。
sqrt()和cbrt()要+0.5卡精度。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <map>
typedef long long LL;

const int MAXN=505;
const LL MOD=998244353;
int n,sizb,sizc;
LL a[MAXN],b[MAXN],c[MAXN];
bool fac[MAXN];
std::map<LL,int> mp;

inline LL gcd(LL x,LL y){
    if(!x||!y) return x+y;
    while(y){
        std::swap(x,y);
        y%=x;
    }
    return x;
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%I64d",&a[i]);
        if(a[i]==1) n--,i--;
    }
    for(int i=1;i<=n;i++){
        LL sq=sqrt(a[i])+0.5;
        if(sq*sq==a[i]){
            fac[i]=1;
            LL sqsq=sqrt(sq)+0.5;
            if(sqsq*sqsq==sq){
                if(mp.find(sqsq)!=mp.end()) mp[sqsq]=mp[sqsq]+4;
                else mp[sqsq]=4;
                continue;
            }
            if(mp.find(sq)!=mp.end()) mp[sq]=mp[sq]+2;
            else mp[sq]=2;
            continue;
        }
        LL cb=cbrt(a[i])+0.5;
        if(cb*cb*cb==a[i]){
            fac[i]=1;
            if(mp.find(cb)!=mp.end()) mp[cb]=mp[cb]+3;
            else mp[cb]=3;
            continue;
        }
        //b[++sizb]=a[i];
    }
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            if(a[i]==a[j]) continue;
            LL d=gcd(a[i],a[j]);
            if(d==1) continue;
            if(!fac[i]){
                if(mp.find(d)!=mp.end()) mp[d]=mp[d]+1;
                else mp[d]=1;
                LL e=a[i]/d;
                if(mp.find(e)!=mp.end()) mp[e]=mp[e]+1;
                else mp[e]=1;
                fac[i]=1;
            }
            if(!fac[j]){
                if(mp.find(d)!=mp.end()) mp[d]=mp[d]+1;
                else mp[d]=1;
                LL e=a[j]/d;
                if(mp.find(e)!=mp.end()) mp[e]=mp[e]+1;
                else mp[e]=1;
                fac[j]=1;
            }
        }
        if(!fac[i]) c[++sizc]=a[i];
    }
    std::sort(c+1,c+sizc+1);
    LL ans=1;
    for(auto it:mp) ans=ans*(it.second+1)%MOD;
    int temp=0;
    for(int i=1;i<=sizc;i++){
        if(i==1||c[i]==c[i-1]) temp++;
        else{
            ans=ans*(temp+1)%MOD*(temp+1)%MOD;
            temp=1;
        }
    }
    ans=ans*(temp+1)%MOD*(temp+1)%MOD;
    printf("%I64d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9770582.html