zoukankan      html  css  js  c++  java
  • 来自星星的祝福(容斥+排列组合)

    来自星星的祝福

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 102 Accepted Submission(s): 9

    Problem Description

    在一个遥远的山区中,流传着一个传说,一个真正的好男人,需要受到来自M个不同星座的女孩子的赞美--“你是个好人”,才会找到真爱。
    毫无疑问,yyf就是这样的好男人。他费尽千辛万苦,找到了瞎子算命师ZJiaQ,ZJiaQ告诉他:你这辈会受到n个女孩子的赞美。
    那么,请问yyf找到真爱的概率有多少?
    假设每个女孩子是M个星座中任一个的概率相等。

    Input

    第一行一个数T(T<=10),表示数据组数。(T可输入多次)
    接下来每组数据中,输入n与m(n<=1000000000000000000(18个零),m<=100)。

    Output

    输出概率的百分比,并且不需要输出小数点后的数字。

    Sample Input

    2
    1 1
    2 2

    Sample Output

    %100
    %50

    分析

    有两种思路
    1.套用容斥定理,我们可以得到如下公式

    [1+sum_{i=m-1}^{1}(-1)^{m-i}(frac{i}{m})^nC_m^i ]

    带入计算即可
    2.令f[i]表示n个人恰好有i个星座的概率,那么f[i]=(m个星座选指定的i个的概率)^n-(i个人选了j个星座的概率)*(j个星座的排列组合
    代入计算即可

    trick

    1.可能出现ans小于0,此时ans变成0

    代码

    //思路1
    #include <bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define F(i,a,b) for(int i=a;i<=b;++i)
    #define R(i,a,b) for(int i=a;i<b;++i)
    #define mem(a,b) memset(a,b,sizeof(a))
    #pragma comment(linker, "/STACK:102400000,102400000")
    inline void read(int &x){x=0; char ch=getchar();while(ch<'0') ch=getchar();while(ch>='0'){x=x*10+ch-48; ch=getchar();}}
    
    double f[101];
    int t;
    ll n,m;
    double work(double x,ll n,ll z)
    {
        double ret=f[m]/f[z]/f[m-z];
        for(;n;n>>=1,x*=x) if(n&1) ret*=x;
            return ret;
    }
    int main()
    {
        f[0]=1;
        for(ll i=1;i<=100;++i) f[i]=f[i-1]*i; 
        while(~scanf("%d",&t))
        {
            while(t--)
            {
                scanf("%lld %lld",&n,&m);
                if(n<m) {printf("%%0
    ");continue;}
                double ans=1;
                for(int i=m-1;i;--i)
                {
                    double ret=work(1.0*i/m,n,i);
                    ans+=(((m-i)&1)?-1:1)*ret;
                }
                if(ans<0) ans=0;
                putchar('%');
                printf("%.f
    ",ans*100);
            }
        }
        return 0;
    }
    
    //思路2
    #include<bits/stdc++.h>
    using namespace std;
    typedef __int64 ll;
    
    long double c[105][105];
    ll n,m;
    long double f[105];
    long double kp(long double x,ll n)
    {
        long double ret=1;
        while(n)
        {
            if (n%2==1) ret*=x;
            n/=2;
            x*=x;
        }
        return ret;
    }
    int main()
    {
        c[0][0]=1;
        for (int i=1;i<=10;i++)
        {
            c[i][0]=1;
            for (int j=1;j<=i;j++)
                c[i][j]=c[i-1][j-1]+c[i-1][j];
        }
        int t;
    
        while(~scanf("%d",&t))
        {
    
            while(t--)
            {
                scanf("%I64d%I64d",&n,&m);
                if (n<m) {printf("%%0
    "); continue;}
                for (int i=1;i<=m;i++)
                {
                    f[i]=kp(1.0*i/m,n);
                    for (int j=1;j<i;j++) f[i]-=f[j]*c[i][j];
                }
                if (f[m]<0) f[m]=0;
                printf("%%%.0f
    ",(double)f[m]*100);
            }
        }
    }
    
  • 相关阅读:
    Eclipse新建工程编译R cannot be resolved to a variable问题
    Eclipse如何生成jar包
    Springmvc+Shiro实战
    封装springmvc处理ajax请求结果
    jquery操作cookie
    探讨jsp相对路径和绝对路径
    spring集成quartz
    Spring-Task
    bootstrap table分页(前后端两种方式实现)
    jquery file upload示例
  • 原文地址:https://www.cnblogs.com/chendl111/p/7107723.html
Copyright © 2011-2022 走看看