ZOJ3868:GCD Expectation

Edward has a set of n integers {a1a2,...,an}. He randomly picks a nonempty subset {x1x2,…,xm}
(each nonempty subset has equal probability to be picked), and would like to know the expectation of [gcd(x1x2,…,xm)]k.

Note that gcd(x1x2,…,xm) is the greatest common divisor of {x1x2,…,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 nk (1 ≤ nk ≤ 106). The second line contains n integers a1a2,…,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次方
输出期望乘以(2^N-1)的值
题目中1的概率是26/31,2的概率是2/32,3,4,5的概率是1/32
期望则是42/32,所以答案为42,也就是说我们的目标是求出期望的分子部分即可

对于N的序列,肯定有2^N-1个非空子集,其中其最大的GCD不会大于原序列的max,那么我们用数组fun来记录其期望
例如题目中的,期望为1的有26个,期望为2的有2个,期望为3,4,5的都只有1个
我们可以拆分来算,首先对于1,期望为1,1的倍数有5个,那么这五个的全部非空子集为2^5-1种,得到S=(2^5-1)*1;
对于2,2的期望应该是2,但是在期望为1的时候所有的子集中,我们重复计算了2的期望,多以我们应该减去重复计算的期望数,现在2的期望应该作1算,那么对于2的倍数,有两个,2,4,其组成的非空子集有2^2-1个,所以得到S+=(2^2-1)*1
对于3,4,5同理;

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <algorithm>
using namespace std;
#define ls 2*i
#define rs 2*i+1
#define up(i,x,y) for(i=x;i<=y;i++)
#define down(i,x,y) for(i=x;i>=y;i--)
#define mem(a,x) memset(a,x,sizeof(a))
#define w(a) while(a)
#define LL long long
const double pi = acos(-1.0);
#define Len 1000005
#define mod 998244353
const LL inf = 1<<30;

LL t,n,k;
LL a[Len];
LL two[Len],fun[Len],cnt[Len],vis[Len],maxn;
LL power(LL x, LL y)
{
    LL ans = 1;
    w(y)
    {
        if(y&1)
            ans=(ans*x)%mod;
        x=(x*x)%mod;
        y/=2;
    }
    return ans;
}
int main()
{
    LL i,j;
    scanf("%lld",&t);
    two[0] = 1;
    up(i,1,Len-1)
    two[i] = (two[i-1]*2)%mod;
    w(t--)
    {
        mem(cnt,0);
        mem(vis,0);
        scanf("%lld%lld",&n,&k);
        maxn = 0;
        up(i,0,n-1)
        {
            scanf("%lld",&a[i]);
            if(!vis[a[i]])
            {
                vis[a[i]] = 1;
                cnt[a[i]] = 1;
            }
            else
                cnt[a[i]]++;
            maxn = max(maxn,a[i]);
        }
        fun[1] = 1;
        up(i,2,maxn)
        fun[i] = power(i,k);
        up(i,1,maxn)
        {
            for(j = i+i; j<=maxn; j+=i)
                fun[j]=(fun[j]-fun[i])%mod;
        }
        LL ans = (two[n]-1)*fun[1]%mod;
        up(i,2,maxn)
        {
            LL cc = 0;
            for(j = i; j<=maxn; j+=i)
            {
                if(vis[j]) cc+=cnt[j];
            }
            LL tem = (two[cc]-1)*fun[i]%mod;
            ans = (ans+tem)%mod;
        }
        printf("%lld\n",(ans+mod)%mod);
    }

    return 0;
}

时间: 2024-08-02 23:08:24

ZOJ3868:GCD Expectation的相关文章

zoj.3868.GCD Expectation(数学推导&gt;&gt;容斥原理)

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 pick

ZOJ 3868 GCD Expectation DP

dp[i] 表示公约数为i时有多少种组合 先预处理一遍dp[i]这是的dp[i]表示含有公约数i或者i的倍数的组合有多少个 再倒着dp dp[i] - = Sigma(dp[j]) (j是i的倍数 2i,3i,4i.....) 结果既为 Sigma[ dp[i]*pow(i,k) ] GCD Expectation Time Limit: 4 Seconds      Memory Limit: 262144 KB Edward has a set of n integers {a1, a2,.

ACM学习历程—ZOJ 3868 GCD Expectation(莫比乌斯 || 容斥原理)

Description 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, 

Zoj 3868 GCD Expectation

给一个集合,大小为n , 求所有子集的gcd 的期望和 . 期望的定义为 这个子集的最大公约数的K次方 : 每个元素被选中的概率是等可能的 即概率 p = (发生的事件数)/(总的事件数); 总的事件数 = 2^n -1; 大小为n的集合的非空子集个数为2^n -1 期望 = p(i) *i; = 1*p(1) + 2*p(2) + ... +n*p(n); 设x发生的事件数为 dp[x] , 则上式可化简为: =1*dp[1]/(2^n-1) + 2*dp[2]/(2^n-1) + ... +

[暴力统计] zoj 3868 GCD Expectation

题意: 给n和k,求n个数的任意非空子集gcd的k次方的期望. 最后期望乘上2^n-1 思路: 因为取每个子集都是等概率,所以取出每个子集的概率是1/(2^n-1) 然而最后的答案是乘上2^n-1 所以其实求的就是每个非空子集的gcd的k次方的和. 然后就是求法了. 我们可以把题目转换成求gcd等于i的非空集合有多少个. gcd从Max枚举到1,求出答案. 对于每个i,设n个数中是i的倍数的数有x个. 那么gcd等于i的个数就是总共的 (2^x-1)个减去gcd等于j的个数,j是i的倍数. 因此

ZOJ GCD Expectation

#include <iostream> #include <cstring> #include <cstdlib> #include <algorithm> #include <string> #include <map> #include <cmath> #include <math.h> #include <cstdio> #define LL long long using namespace

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

模拟3

    ID Origin Title 6 / 12 Problem A ZOJ 3860 Find the Spy 6 / 27 Problem B ZOJ 3861 Valid Pattern Lock     Problem C ZOJ 3862 Intersection   0 / 1 Problem D ZOJ 3863 Paths on the Tree     Problem E ZOJ 3864 Quiz for EXO-L     Problem F ZOJ 3865 Supe

15th浙大校赛 zoj3860-3868

比赛链接: here 题目对应到ZOJ3860~3868 A Find the Spy 水 #include<cstdio> #include<map> #include<cstring> #include<iostream> using namespace std; map<int,int>mp; map<int,int>::iterator it; int main() { int T,n,x; scanf("%d&qu