Gaming of Co-prime Disallowance(概率 莫比乌斯)

http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1007&cid=886

题意:

n张牌,双方走,每次删除一张牌,没有牌可以删除的lost,删除后所有删除的牌gcd=1的lost。双方随机删除,问先手win的概率

解析:

考虑分析gcd=1前的gcd=G。

假设G的倍数有 X X X个,非G倍数有 Y Y Y个。

那么输的概率为 X X + Y X − 1 X + Y − 1 2 X + Y − 2 + . . . \dfrac{X}{X+Y}\dfrac{X-1}{X+Y-1}\dfrac{2}{X+Y-2}+... X+YXX+Y1X1X+Y22+...(选2个G的倍数后选1个非G的倍数,选4个G的倍数后选1个非G的倍数……)

但是G=6被计算两次,所以用莫比乌斯函数消去重复计算。

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2020-08-13-12.11.10
 */
#include
using namespace std;
#define LL long long
#define LD long double
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair
#define fi first
#define se second
void test(){cerr<<"\n";}
template<typename T,typename... Args>void test(T x,Args... args){cerr<<"> "<<x<<" ";test(args...);}
const LL mod=1e9+7;
const int maxn=1e5+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/

namespace mobius{
int mu[maxn],pri[maxn>>1],now;
bool vis[maxn];

void init(){
    mu[1]=1;
    for(int i=2;i<maxn;i++){
        if(!vis[i]){
            pri[++now]=i;
            mu[i]=-1;
        }
        for(int j=1;j<=now&&pri[j]*i<maxn;j++){
            vis[pri[j]*i]=1;
            if(i%pri[j])mu[i*pri[j]]=-mu[i];
            else{
                mu[i*pri[j]]=0;
                break;
            }
        }
    }
}
}

LD P[109][109]; /// [num g][num not g]
vector<int>pri[maxn];
void init(){
    rep(i,1,1e5){
        for(int j=1;j*j<=i;j++){
            if(i%j==0){
                pri[i].pb(j);
                if(j*j!=i){
                    pri[i].pb(i/j);
                }
            }
        }
    }
    rep(i,2,100){
        rep(j,1,100){
            if(i+j>100)break;
            LD I=i,J=j;
            LD p=1;
            rep(_,1,i){///GCD删除的数量
                p*=I/(I+J);
                I-=1;

                if(_%2==0){
                    P[i][j]+=p*(J/(I+J));
                }
            }
        }
    }
}

int cnt[maxn];

int main(){
    mobius::init();
    init();
    int t=rd;
    while(t--){
        int cnt_1=0;
        mmm(cnt,0);
        int n=rd;
        int G=-1;
        rep(i,1,n){
            int val=rd;
            if(val==1)cnt_1++;
            if(G==-1)G=val;
            else G=__gcd(G,val);
            for(auto p:pri[val]){
                cnt[p]++;
            }
        }
        if(G>1){
            if(n&1){
                printf("%.10f\n",1.);
            }
            else{
                printf("%.10f\n",0.);
            }
            continue;
        }
        LD ans=(LD)cnt_1/(LD)n;
        rep(i,2,1e5){
            ans-=mobius::mu[i]*P[cnt[i]][n-cnt[i]];
        }
        printf("%.10f\n",1-(double)ans);
    }
    return 0;
}
/*
1
4
2 2 3 6
*/
/*_________________________________________________________end*/

你可能感兴趣的:(数论/数学,例题)