zoukankan      html  css  js  c++  java
  • 汕头市队赛SRM 20 T2不净的圣杯

    不净的圣杯 SRM 20

    背景


            作为一张BUG级别的卡,官方打算把它修改得人畜无害一些……

            虽然名字还没想好,但是能力大概是对敌方所有单位造成d点伤害,d为自己牌组中所有卡的编号的最大公约数。这无疑是一个全新的技能类型,决定一出,负责“自动编辑卡组”系统的工程师们发愁了,要如何让AI把这一鬼畜设定考虑进去呢?我们现在只能假定每张牌被编进卡组的概率是相等的,工程师们想知道d的期望值。

    描述

            给n个数,问随机从中挑出一些数(大于等于1个)后,挑出数字的期望gcd。输出期望值乘(2^n-1)并对1e9+7取模后的值。

    输入格式

            第一行两个正整数n,m。

            第二行n个不超过m的正整数。

    输出格式

            一个整数,期望值乘(2^n-1)并对1e9+7取模后的值。

    样例输入

    3 5
    1 2 3

    样例输出

    10

    数据范围

    测试点 n m
    1 10 10^4
    2 10 10^4
    3 10 10^4
    4 20 10^4
    5 10^4 10^4
    6 10^5 10^5
    7 10^5 10^6
    8 10^5 10^6
    9 10^5 10^6
    10 10^5 10^6

    样例解释

            答案为1*5+2*1+3*1=10

    —————————————————————————

    这题一眼看去很明显的就是莫比乌斯反演(主观臆断QAQ

    g(x)就是以x为gcd的方案数(子集数) 

    f(x)就是以x(及x的倍数)为gcd的方案数

    f(x)可以暴力求O(mlogm) 可以先求出T(x)就是以是x倍数的数的个数

    f(x)=2^T(x)-1 至于莫比乌斯函数mu(x)可以线性筛 这样之后及可以求答案辣

    那个乘上2^n-1其实就是为了抵消期望而已 题目就是求gcd和

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long
    const int M=1e6+7,mod=1e9+7;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    LL ans,g[M],n,m,k,w[M],t[M];
    LL ly[M],f[M],vis[M],mu[M],cnt,p[M];
    void prepare(){
        ly[0]=1; for(int i=1;i<=m;i++) ly[i]=ly[i-1]*2%mod;
        mu[1]=1;
        for(int i=2;i<=m;i++){
            if(!vis[i]){p[++cnt]=i;mu[i]=-1;}  
            for(int j=1;j<=cnt&&i*p[j]<=m;j++){
                vis[i*p[j]]=1;  
                if(i%p[j]) mu[i*p[j]]=-mu[i];  
                else{mu[i*p[j]]=0; break;}  
            }
        } 
    }
    int main(){
        n=read(); m=read();
        prepare();
        for(int i=1;i<=n;i++) k=read(),w[k]++;
        for(int i=1;i<=m;i++){
            for(int j=i;j<=m;j+=i) t[i]=(t[i]+w[j])%mod;
            f[i]=(ly[t[i]]-1+mod)%mod;
        }
        for(int i=1;i<=m;i++) for(int k=1;k*i<=m;k++) g[i]=(g[i]+mu[k]*f[k*i]%mod)%mod;
        for(int i=1;i<=m;i++) ans=(ans+g[i]*i%mod)%mod;
        printf("%lld
    ",(ans+mod)%mod);
        return 0;
    }
    View Code
  • 相关阅读:
    Python 基础之函数初识与函数参数
    python 基础之浅拷贝与深拷贝
    Python 基础之集合相关操作与函数和字典相关函数
    Python 基础之字符串操作,函数及格式化format
    Rocket
    Rocket
    Rocket
    Rocket
    Rocket
    Rocket
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7629230.html
Copyright © 2011-2022 走看看