题目链接:
http://172.16.0.132/senior/#main/show/4668
题目:
题解:
考虑把A数组里的每个元素分解质因数,对于每个质因数开一个vector存一下包含这个质因数的元素对应的这个质因数的指数
我们可以枚举质因数分别处理。为什么时间复杂度是对的呢?因为对于任何一个元素质因数种类是不会很多的,而对于每个质因数我们仅考虑包含它的数而不是全部扫一遍,因而是对的
枚举质因数之后,我们得到它对应的指数序列。对于小于等于根号1e7的质因数,考虑把这个指数序列从小到大,对于某个位置与之前位置的贡献就是靠前位置的指数,因此我们不断累加前缀统计答案就好了;对于另外的质因数,可以发现包含它的指数序列只能是1,所以我们不需要排序可以直接得到答案(注意到要求计算的数列其实就是元素之间两两只算一次,但注意还需要算上和本身的gcd)
这个模数比较坑,直接乘取模的话会爆long long,因此我们采用慢速乘(不是类似快速幂的那种)
比如x*y,我们令inf=1e7
$a1=x mod inf$
$a2=x/inf$
$b1=y mod inf$
$b2=y/inf$
我们拆开来计算就是了,具体看代码
#include<algorithm> #include<cstring> #include<cstdio> #include<iostream> #include<cmath> #include<vector> using namespace std; typedef long long ll; const int N=4e4+15; const ll mo=1e11+9; const int M=1e6+15; const ll inf=1e7+15; int n,cnt; int a[N],vis[inf]; ll p[N]; vector <int> pi[M]; inline int read() { char ch=getchar();int s=0,f=1; while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();} return s*f; } void div(int x) { for (int i=2;i*i<=x;i++) { if (x%i) continue; if (!vis[i]) p[++cnt]=i,vis[i]=cnt; int s=0; while (x%i==0) x/=i,++s; pi[vis[i]].push_back(s); } if (x>1) { if (!vis[x]) p[++cnt]=x,vis[x]=cnt; pi[vis[x]].push_back(1); } } ll mul(ll x,ll y) { ll a1=x%inf; ll a2=x/inf; ll b1=y%inf; ll b2=y/inf; ll re=0; re=(re+a2*inf%mo*b2%mo*inf%mo)%mo; re=(re+a2*inf%mo*b1%mo)%mo; re=(re+a1*inf%mo*b2%mo)%mo; re=(re+a1*b1%mo)%mo; return re; } ll qpow(ll x,ll y) { ll re=1; for (;y;y>>=1,x=mul(x,x)) if (y&1) re=mul(re,x); return re; } int main() { n=read(); for (int i=1;i<=n;i++) a[i]=read(),div(a[i]); ll ans=1; for (int i=1;i<=cnt;i++) { if (1ll*p[i]*p[i]<=inf) { int pnt=pi[i].size(); sort(pi[i].begin(),pi[i].end()); ll s=0; for (int j=0;j<pnt;j++) { ans=mul(ans,qpow(p[i],s)); s+=pi[i][j]; } } else { ll c=pi[i].size(); ans=mul(ans,qpow(p[i],c*(c-1)/2)); } } for (int i=1;i<=n;i++) ans=mul(ans,1ll*a[i]); printf("%lld ",ans); return 0; }