题意就是求序列的所有 gcd 的 k 次方和。
F(d) 表示 d|gcd(x1,x2,...,xm) 的组数。
F(x)=∑x|df(d)
f(x)=∑x|dμ(dx)∗F(d)
F(d) 求法:
d|x1,d|x2,d|x3,...,d|xm
,
n
个数中
每一次 ai 的最大值为 mx 。
o(mx) 的复杂度内预处理出 F(d) 的值。
预处理完了以后 o(mxlog(mx)) 处理出 f(x) 的值。
要求的答案: ans=∑ni=1f(i)∗ik 这里 omxlogk) 的复杂度搞定。
总的复杂度: o(mxlog(mx)+mxlogk) 。
代码部分:
#include <bits/stdc++.h>
#define LL long long
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
using namespace std;
const LL Mod = 998244353;
const int maxn = 1000010;
LL quickpow(LL a,int n,LL m){
LL ans=1;
while(n){
if(n&1) ans = (ans*a)%m;
a = (a*a)%m;
n>>=1;
}
return ans;
}
LL c[maxn];//预处理出2^n次方
//cnt[x]表示x|a[i]的个数
int prime[maxn],mu[maxn],cnt[maxn];
bool check[maxn];
void Mobius(){
memset(check,false,sizeof(check));
prime[0] = 0;
mu[1] = 1;
FOR(i,2,maxn){
if(!check[i]){
prime[++prime[0]] = i;
mu[i] = -1;
}
FOR(j,1,prime[0]+1){
if(i*prime[j] >= maxn) break;
check[i*prime[j]] = true;
if(i % prime[j]){
mu[i*prime[j]] = -mu[i];
}
else{
mu[i*prime[j]] = 0;
break;
}
}
}
c[0] = 1;
FOR(i,1,maxn){
c[i] = c[i-1]<<(1LL);
c[i] %= Mod;
}
}
//F[d]表示d|gcd(b1,b2,...,bp)的个数
//f[d]表示d=gcd(b1,b2,...,bp)的个数
LL F[maxn],f[maxn];
int n,k,mx;
void init(){
scanf("%d%d",&n,&k);
memset(cnt,0,sizeof(cnt));
memset(F,0,sizeof(F));
memset(f,0,sizeof(f));
int num;
mx = -1;
FOR(i,0,n){
scanf("%d",&num);
mx = max(mx,num);
cnt[num] ++;
}
FOR(i,1,mx+1){
for(int j = i+i;j <= mx;j += i){
cnt[i] += cnt[j];
}
F[i] = (c[cnt[i]]+Mod-1)%Mod;;
}
FOR(i,1,mx+1){
for(int j = i;j <= mx;j += i){
f[i] += mu[j/i]*F[j];
f[i] %= Mod;
}
}
}
void work(){
LL ans = 0;
FOR(i,1,mx+1){
if(!f[i]) continue;
LL res = (f[i] * quickpow(i,k,Mod))%Mod;
ans += res;
ans %= Mod;
}
printf("%lld\n",ans);
}
int main()
{
//freopen("test.in","r",stdin);
Mobius();
int T; scanf("%d",&T);
while(T--){
init();
work();
}
return 0;
}