枚举gcd(l,r)=d的倍数,则b[i]可能的值为{d,2d,3d,...,floor(a[i]/d)∗d}
则gcd(l,r)=d的倍数时,方案数=∏ni=1a[i]d
显然剩下就是容斥了
而莫比乌斯函数mu[i]=−1k,k=i的素因子个数
ans=∑ni=1{(−mu[i])∗∏nj=1a[j]i}
显然大暴力O(n2)爆炸
维护一个sum[i]=∑nj=1(a[j]<=i)
则确定i,k时,满足a[j]i=k的j数量为sum[(k+1)∗i−1]−sum[k∗i−1]
则gcd=i倍数时的方案数=∏n/ik=1ksum[(k+1)∗i−1]−sum[k∗i−1]
ans=∑ni=1∏k=n/ik=1ksum[(k+1)∗i−1]−sum[k∗i−1]
最终需要O(nlogn∗(1+12+13+...))=O(nlogn∗调和级数)=大概是...O(nlogn(ln(n+1)+r))
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<string.h>
#include<string>
#include<math.h>
#include<memory.h>
#include<queue>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))
using namespace std;
//const int inf=0x3f3f3f3f;
const int MOD = 1e9+7;
const int N = 1e5 + 5;
const int inf=MOD;
const int MAXN = 100000;
bool check[MAXN+10];
int prime[MAXN+10];
int mu[MAXN+10];
void Moblus()
{
memset(check,false,sizeof(check));
mu[1] = 1;
int tot = 0;
for(int i = 2; i <= MAXN; i++)
{
if( !check[i] ){
prime[tot++] = i;
mu[i] = -1;
}
for(int j = 0; j < tot; j++)
{
if(i * prime[j] > MAXN) break;
check[i * prime[j]] = true;
if( i % prime[j] == 0){
mu[i * prime[j]] = 0;
break;
}else{
mu[i * prime[j]] = -mu[i];
}
}
}
}
int sum[N];
int a[N];
ll qPow(ll a,int n){
ll ans=1;
ll t=a%MOD;
while(n){
if(n&1){
ans=(ans*t)%MOD;
}
n>>=1;
t=(t*t)%MOD;
}
return ans;
}
ll w(int x,int n){
if(sum[x-1]){
return 0;
}
ll ans=1;
for(int i=1;i*x<N-1;++i){
ll t=qPow(i,sum[min((i+1)*x-1,N-1)]-sum[min(N-1,i*x-1)]);
ans=(ans*t)%MOD;
}
return ans;
}
ll slove(int n){
ll ans=0;
for(int i=2;i<=n;++i){
ans+=(-w(i,n)*mu[i])%MOD;
ans%=MOD;
}
return (ans+MOD)%MOD;
}
int main()
{
//freopen("/home/lu/code/r.txt","r",stdin);
Moblus();
int T;
scanf("%d",&T);
for(int tt=1;tt<=T;++tt){
int n;
MEM(sum,0);
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
++sum[a[i]];
}
for(int i=1;i<N;++i){
sum[i]+=sum[i-1];
}
printf("Case #%d: %lld\n",tt,slove(n));
}
return 0;
}