比赛没搞出来。不知道借助莫比乌斯函数容斥。菜。
枚举除数时,除数相同的为一块,还可以优化。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
const ll md = 1e9 + 7;
bool check[MAXN + 10];
int prime[MAXN + 10];
int tot = 0;
int mu[MAXN + 10];
void Moblus()
{
memset(check, 0, sizeof(check));
mu[1] = 1;
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];
}
}
}
} //线性筛求Moblus函数
int n, a[MAXN];
ll sum[MAXN * 2];
void init()
{
memset(sum, 0, sizeof(sum));
}
ll mypow(ll b, int k)
{
ll ret = 1;
while (k){
if (k & 1)
ret *= b;
ret %= md;
b *= b;
b %= md;
k >>= 1;
}
return ret;
}
int main()
{
Moblus();
int T;
scanf("%d", &T);
for (int kase = 1; kase <= T; kase++){
init();
int mx = -1e9, mi = 1e9;
scanf("%d", &n);
for (int i = 1; i <= n; i++){
scanf("%d", &a[i]);
mx = max(mx, a[i]);
mi = min(mi, a[i]);
sum[a[i]]++;
}
if (n == 1){
printf("Case #%d: %lld\n", kase, (ll)a[1] - 1);
continue;
}
for (int i = mi; i < MAXN * 2; i++){
sum[i] += sum[i - 1];
}
ll ans = 0;
for (int i = 2; i <= 100000; i++){ //枚举除数
if (i > mi)break;
if (mu[i] == 0)continue;
ll fuhao = -mu[i];
int p = i;
ll cnt = 1;
while (p <= mx){
int tmp = sum[p + i - 1] - sum[p - 1]; //除数相同的块
cnt *= mypow(p / i, tmp);
cnt %= md;
p += i;
}
ans += fuhao*cnt;
ans = (ans + md) % md; //wa1
}
printf("Case #%d: %lld\n", kase, ans);
}
return 0;
}