版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sizeof_you/article/details/82968325
还是某个老师讲的题
很重要的一点:
分析一个式子能不能用线性筛,只需要看式子中每一个质因子是不是都可以独立出来
所以就可以把式子中的未知量用质因子的多少次方来表示
看能不能拆成质因子互相独立的部分
这也是一种套路,很多复杂度很高的题只要拆成质因子来表达就会变得快很多,因为质数是很少的
这道题是同理的,分析可以表达成只和质因子有关的式子,所以就可以先分解质因数,再求解
emmm写起来太麻烦就不写了quq(注意要单独考虑1)
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 2500005
#define LL long long
using namespace std;
int n,tot;
LL ans=1,sum[30];
const int mod=1e9+7;
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
struct evepri{
int p,num;
bool operator <(const evepri &x) const{
return p<x.p||(p==x.p && num<x.num);
}
}pri[maxn];
inline void decompose(int x){
int tmp=x;
for(int i=2;i<=sqrt(x);i++){
if(tmp==1 || tmp<i) break;
if(tmp%i==0){
pri[++tot].p=i;
while(tmp%i==0) tmp/=i,pri[tot].num++;
}
}
if(tmp>1) pri[++tot].p=tmp,pri[tot].num=1;
}
inline LL qpow(LL x,int k){
LL ret=1;
while(k){
if(k&1) (ret*=x)%=mod;
(x*=x)%=mod; k>>=1;
} return ret;
}
inline void calc(int l,int r){
memset(sum,0,sizeof sum); sum[0]=1;
LL nowp=pri[l].p,res=1;
for(int i=1;i<=pri[r].num;i++)
sum[i]=(sum[i-1]*nowp)%mod;
for(int i=1;i<=pri[r].num;i++)
(sum[i]+=sum[i-1])%=mod;
for(int i=l;i<=r;i++)
(res*=sum[pri[i].num])%=mod;
res=(res-1+mod)%mod;
res=res*qpow(nowp,mod-2)%mod; (res*=(nowp-1))%=mod;
ans=ans*(res+1)%mod;
}
int main(){
n=rd();
for(int i=1;i<=n;i++){
int x=rd();
decompose(x);
}
sort(pri+1,pri+tot+1);
int lst=0;
for(int i=1;i<=tot;i++){
if(i==tot || pri[i].p!=pri[i+1].p)
calc(lst+1,i),lst=i;
}
printf("%lld\n",ans);
return 0;
}