GCD Expectation
Time Limit: 4 Seconds Memory Limit: 262144 KB
Edward has a set of n integers {a1, a2,…,an}. He randomly picks a nonempty subset {x1, x2,…,xm} (each nonempty subset has equal probability to be picked), and would like to know the expectation of [gcd(x1, x2,…,xm)]k.
Note that gcd(x1, x2,…,xm) is the greatest common divisor of {x1, x2,…,xm}.
Input
There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:
The first line contains two integers n, k (1 ≤ n, k ≤ 106). The second line contains n integers a1, a2,…,an (1 ≤ ai ≤ 106).
The sum of values max{ai} for all the test cases does not exceed 2000000.
Output
For each case, if the expectation is E, output a single integer denotes E · (2n - 1) modulo 998244353.
Sample Input
1
5 1
1 2 3 4 5
Sample Output
42
从N个数中随即取任意个数,他们的gcd的k次方的期望,要求的是E*(2^n-1),所以就是要求任意个数的gcd的k次方的和。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <string.h>
#define LL long long
#define scan(a) scanf("%d",&a)
#define REP(i,a,b) for(int i=a;i<b;++i)
#define mset(a,b) memset(a,b,sizeof a)
//#define maxn 1e6+10
using namespace std;
const LL mod = 998244353;
const int maxn = 1e6+10;
LL F[maxn];
LL pow2[maxn];
int k;
int miu[maxn];
int a[maxn];
bool check[maxn];
int prime[maxn];
void Moblus()
{
mset(check,0);
miu[1]=1;
int tot=0;
for(int i=2;i<=maxn ;++i)
{
if(!check[i])
{
prime[tot++]=i;
miu[i]=-1;
}
REP(j,0,tot)
{
if(i*prime[j] >maxn) break;
check[i*prime[j]]=true;
if(i%prime[j] ==0)
{
miu[i*prime[j]] = 0;
break;
}
else
{
miu[i*prime[j]] = -miu[i];
}
}
}
}
LL _pow(LL d,int k)
{
if(k==1) return d%mod;
LL ret=_pow(d,k/2) ;
ret *=ret;
ret%=mod;
if(k&1)
ret=ret*d;
return ret%mod;
}
int maxan=0;
void preF(int n)
{
mset(F,0);
maxan=0;
REP(i,0,n)
{
F[a[i]]++;
maxan=max(maxan,a[i]);
}
F[1]=n;
REP(i,2,maxan+1)
{
for(int j=i+i;j<=maxan;j+=i)
{
F[i] += F[j];
F[i]%=mod;
}
}
REP(i,1,maxan+1)
{
F[i]=pow2[F[i]]-1;
if(F[i]<0) F[i]+=mod;
}
}
LL solve()
{
LL ret=0;
LL sum=0;
REP(i,1,maxan+1)
{
sum=0;
for(int j=i;j<=maxan;j+=i)
{
sum+= miu[j/i]*F[j];
sum%=mod;
}
if(i>1) sum=sum*_pow(i,k);
sum%=mod;
ret+=sum;
if(ret>=mod) ret-=mod;
}
return ret;
}
int main()
{
Moblus();
pow2[0]=1;
REP(i,1,maxn)
pow2[i]=pow2[i-1]*2%mod;
int t,n;
cin>>t;
while(t--)
{
cin>>n>>k;
REP(i,0,n)
scan(a[i]);
preF(n);
LL ans=solve();
cout<<ans<<endl;
}
}