搞了两天发现是qpow时大数相乘爆精度了,以前没遇到过,因为大数检测时模数达到了1e18,所以qpow可能会爆,应该利用快速幂原理写一个快速加即可。
先筛出1e6以内的质数,然后把x里<=1e6的质因子筛完,这时候x里至多有两个大于1e6因子,可以同时miller下把质数统计走,这样剩下的数都是P1*P2的形式,由于我们只需要知道不同种类因子的个数,可以对剩下的数先两两判断是否不相等且gcd>1,这样就可以把这两个数拆分为四个质因子统计。之后再遍历剩下的数,用之前统计的质因子尝试是否可以被整除,可以的话就把x拆分为两个质因子统计。最后剩下的数含有的质因子就是独特的了。要注意可能出现P1*P1的情况,特判。
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<map> 5 #include<unordered_map> 6 #include<bits/stdc++.h> 7 using namespace std; 8 #define LL long long 9 const LL maxn=1000005; 10 const LL mod=1e9+7; 11 unordered_map<LL,LL>M; 12 unordered_map<LL,LL>::iterator it; 13 LL A[555]; 14 vector<LL>prime; 15 bool is[1000010]; 16 LL gcd(LL a,LL b){ 17 return b==0?a:gcd(b,a%b); 18 } 19 LL Mult(LL x,LL y,LL mod){ //避免两个long long相乘溢出 20 LL ans=0;ans%=mod; 21 if(!y)return 0; 22 while(y){ 23 if(y&1){ 24 ans+=x; 25 if(ans>=mod)ans-=mod; 26 } 27 y>>=1;x<<=1; 28 if(x>=mod)x-=mod; 29 } 30 return ans; 31 } 32 LL qpow(LL a,LL b,LL c){ 33 if(a==0) return 0; LL r=1; 34 for(;b;b>>=1,a=Mult(a,a,c)) if(b&1)r=Mult(r,a,c); 35 return r; 36 } 37 LL random(LL n){ 38 return (LL)((double)rand()/RAND_MAX*n+0.5); 39 } 40 int judge(LL n){ 41 for(int i=0;i<20;++i){ 42 if(qpow(random(n-2)+1,n-1,n)!=1) return 0; 43 } 44 return 1; 45 } 46 void init(){ 47 is[0]=is[1]=1; 48 for(LL i=2;i<=maxn;++i){ 49 if(!is[i]){ 50 prime.push_back(i); 51 } 52 for(LL j=0;j<prime.size()&&i*prime[j]<=maxn;++j){ 53 is[i*prime[j]]=1; 54 if(i%prime[j]==0)break; 55 } 56 } 57 } 58 bool all(LL n){ 59 LL m=sqrt((long double)n); 60 if(m*m==n||(m+1)*(m+1)==n||(m-1)*(m-1)==n)return 1; 61 return 0; 62 } 63 vector<LL>S; 64 int main() 65 { 66 init(); 67 LL n,i,j,ans=1; 68 scanf("%lld",&n); 69 for(i=1;i<=n;++i)scanf("%lld",A+i); 70 for(i=1;i<=n;++i){ 71 if(judge(A[i])){ 72 M[A[i]]++; 73 A[i]=1; 74 continue; 75 } 76 for(j=0;j<prime.size()&&prime[j]*prime[j]<=A[i];++j){ 77 if(A[i]%prime[j]==0){ 78 do{ 79 M[prime[j]]++; 80 A[i]/=prime[j]; 81 }while(A[i]%prime[j]==0); 82 if(A[i]>1 && judge(A[i])){ 83 M[A[i]]++; 84 A[i]=1; 85 break; 86 } 87 } 88 } 89 } 90 for(i=1;i<=n;++i){ 91 if(A[i]==1)continue; 92 for(j=i+1;j<=n;++j){ 93 if(A[j]==1 || A[i]==A[j]) continue; 94 LL ret=gcd(A[i],A[j]); 95 if(ret!=1){ 96 M[ret]+=2; 97 if(A[i]/ret!=1)M[A[i]/ret]++; 98 if(A[j]/ret!=1)M[A[j]/ret]++; 99 A[i]=A[j]=1; 100 } 101 } 102 } 103 for(i=1;i<=n;++i){ 104 if(A[i]!=1){ 105 for(it=M.begin();it!=M.end();it++){ 106 if(A[i]%(it->first)==0){ 107 A[i]/=it->first; 108 it->second++; 109 M[A[i]]++; 110 A[i]=1; 111 } 112 } 113 } 114 } 115 for(i=1;i<=n;++i){ 116 if(A[i]!=1)S.push_back(A[i]); 117 } 118 sort(S.begin(),S.end()); 119 S.push_back(1); 120 i=0; 121 LL x=1; 122 while(i<S.size()-1){ 123 while(S[i+1]==S[i])i++,x++; 124 if(all(S[i])) (ans*=(x*2+1))%=mod; 125 else (((ans*=(x+1))%=mod)*=(x+1))%=mod; 126 i++,x=1; 127 } 128 for(it=M.begin();it!=M.end();it++) 129 if(it->first!=1)(ans*=(it->second+1))%=mod; 130 printf("%lld\n",ans); 131 return 0; 132 }