求gcd(xxxxxx)>=2 ,那就是ans=a1*a2*...an - gcd(xxxxx)=1
那么令f(i)为gcd(xxxxx)=i的序列数目,F(i)为gcd(xxxxx)=i的倍数的数目
由莫比乌斯反演,我们要求的f(1)=
从xushu的题解里面盗了张图。。。而我们一般的下底优化是sigma,这里是连乘,思路是一样的。枚举aj/i的答案k,找到a数组中有多少个答案是为k的,用桶来装ai并处理处前缀和,那么就是sum[k*(i+1)-1]-sum[k*i]个a数组中的数,使得aj/i=k。于是就用快速幂处理。
#include<cstdio>
#include<cstring>
#include<cmath>
#define maxl 100010
#define mod 1000000007
#define inf 2000000001
long long n,m,mini,mx,cas;
long long ans;
long long a[maxl],mu[maxl],p[maxl];
long long sum[maxl];
bool no[maxl];
void shai()
{
long long t,j;
mu[1]=1;
for(long long i=2;i<maxl;i++)
{
if(!no[i])
{
p[++p[0]]=i;
mu[i]=-1;
}
t=p[1]*i,j=1;
while(t<maxl && j<=p[0])
{
no[t]=true;
if(i%p[j]==0)
{
mu[t]=0;
break;
}
mu[t]=-mu[i];
t=p[++j]*i;
}
}
}
long long min(long long a,long long b)
{
if(a<b)
return a;
else
return b;
}
void prework()
{
mini=inf;mx=0;
memset(sum,0,sizeof(sum));
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
sum[a[i]]++;
if(a[i]<mini)
mini=a[i];
if(a[i]>mx)
mx=a[i];
}
for(int i=1;i<maxl;i++)
sum[i]+=sum[i-1];
}
long long qp(long long a,long long b)
{
long long ans=1,cnt=a;
while(b)
{
if(b&1)
ans=(ans*cnt)%mod;
cnt=(cnt*cnt)%mod;
b>>=1;
}
return ans;
}
void mainwork()
{
ans=0;
long long pos,t,mul;
for(int i=1;i<=mini;i++)
{
if(mu[i]==0) continue;
t=1;
for(int j=i,k=1;j<=mx;j+=i,k++)
{
pos=min(mx,j+i-1);
t=(t*qp(k,sum[pos]-sum[j-1]))%mod;
}
ans=((ans+(mu[i]*t)%mod)%mod+mod)%mod;
}
mul=1;
for(int i=1;i<=n;i++)
mul=(mul*a[i])%mod;
ans=((mul-ans)%mod+mod)%mod;
}
void print()
{
printf("Case #%lld: %lld\n",cas,ans);
}
int main()
{
long long t;
shai();
scanf("%lld",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}