ZOJ 3868 GCD Expectation 莫比乌斯反演

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


5 1 
1 2 3 4 5

Sample Output

42



题目意思;

从N个数中随即取任意个数,他们的gcd的k次方的期望,要求的是E*(2^n-1),所以就是要求任意个数的gcd的k次方的和。


分析:

设f(d)为gcd=d的取法的种数。那么我们要求的答案就是sigma(f(d)*d^k)。再设F(d)为d | gcd的种数,f就可以通过F反演求得。对于F(d),我们可以预处理出来,先求出n个数中有多少个数可以整除d,然后取法就是2^F(d)-1种。


#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;
    }

}


















你可能感兴趣的:(ZOJ 3868 GCD Expectation 莫比乌斯反演)