思路:
1、显然B的取值范围为 (2,MIN(A))
2、枚举数列A中的每一个数,对于每一个Ai,再枚举2~MIN(A) 中每一个可由不同质因子相乘的数(设为 w:2、 3、5、6、7、10、11……) 对于每一种wi,求解每一个Ai对其的贡献,最后所有wi的贡献值相加即为答案
3、用快速幂优化第2步,需要预处理出每一个Ai出现的次数,再转化为累计的次数差,具体见代码
4、每一个wi都有n个质因子相乘,由容斥原理可知,若n为奇数则该加上,否则减去
5、可以用莫比乌斯反演,预处理出所有数的质因子个数的奇偶性
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define N 100005
#define M 105
#define INF 0x3f3f3f3f
#define mod 1000000007
int t;
//比赛用dfs 代替 莫演,妥妥超时
/*int prime[N];
int tot = 0;
bool is_prime[N*2];
void get_prime()
{
for(int i=2;i<N*2;i++){
if(!is_prime[i]){
prime[tot++] = i;
for(int j=i+i;j<N;j+=i) is_prime[j] = 1;
}
}
}*/
int sum[N<<1];
int mp[N];
// mp[i] == 1 表示质因子不重复且个数为偶
// mp[i] ==-1 表示质因子不重复且个数为奇
// mo[i] == 0 表示存在重复的质因子
//bool has[N*2];
//int q[N];
/*void dfs(int cot,LL num,int p,int min_num)
{
//cout<<num<<endl;//getchar();
if(num>min_num) return;
if(prime[p]>min_num) return;
if(num) mp[num] = cot;
if(num*prime[p]>min_num) return;
dfs(cot+1,num*prime[p],p+1,min_num);
dfs(cot,num,p+1,min_num);
has[num] = 1;
}*/
LL qpow(LL a,LL b)
{
LL ans = 1;
while(b){
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
int main()
{
//get_prime();
//dfs(0,1,0,N-1);
int t;
int cas = 1;
scanf("%d",&t);
mp[1] = 1;
for(int i=1;i<=N-1;i++){
for(int j=i+i;j<=N-1;j+=i){
mp[j] -= mp[i];
}
}
while(t--){
int n;
scanf("%d",&n);
int min_num = INF;
memset(sum,0,sizeof(sum));
for(int i=0;i<n;i++){
int a;
scanf("%d",&a);
sum[a]++; //预处理出每一个Ai出现的次数
min_num = min(min_num,a);
}
for(int i=1;i<=200000;i++) sum[i] += sum[i-1]; //再转化为累计的次数差
LL ans = 0;
for(int i=2;i<=min_num;i++){ //枚举每一个数
if(mp[i]==0) continue; //mo[i] = 0 表示存在重复的质因子
LL tol = 1;
for(int j=1;j*i<=100000;j++){
tol = tol * qpow((LL)j,(LL)sum[(j+1)*i-1] - sum[(i*j)-1]) % mod; //有几个数其大小范围为 j 个 i
}
if(mp[i]==-1) ans = (ans + tol) % mod; // mp[i] == -1 表示质因子不重复且个数为奇
else ans = (ans - tol + mod) % mod;
}
printf("Case #%d: %lld\n",cas++,ans);
}
}