zoukankan      html  css  js  c++  java
  • Luogu P4204 神奇口袋 题解报告

    题目传送门

    【题目大意】

    一个口袋里装了t种颜色的球,第i种颜色的球的数目为a[i],每次随机抽一个小球,然后再放d个这种颜色的小球进口袋。

    给出n个要求,第x个抽出的球颜色为y,求满足条件的概率。

    【思路分析】

    抽出一个球颜色为i的概率设为f[i],球的总数为sum

    在第k步时,$f[i]=frac{a[i]}{sum}$

    那么在k+1步就有两种情况:

    1.第k步抽中了颜色为i的球,那么此时概率为$frac{a[i]}{sum}*frac{a[i]+d}{sum+d}$

    2.第k步没有抽中,那么此时概率为$(1-frac{a[i]}{sum})*frac{a[i]}{sum+d}$

    所以第k+1步时,$f[i]=(1-frac{a[i]}{sum})*frac{a[i]}{sum+d}+frac{a[i]}{sum}*frac{a[i]+d}{sum+d}=frac{a[i]*(sum-a[i]+a[i]+d)}{sum*(sum+d)}=frac{a[i]}{sum}$

    由此可得,在任意时刻抽到某一种颜色的小球的概率是不变的,始终为$frac{a[i]}{sum}$

    如果这道题没有条件的话,到这里就可以完美解决了,但是我们还要考虑题目的条件。

    这里有一个结论:要求中某一步要取的颜色出现的顺序对概率并没有影响。

    假设现在的两个要求中的小球颜色分别为i,j

    1.若i在前,概率$P1=frac{a[i]}{sum}*frac{a[j]}{sum+d}$

    2.若j在前,概率$P2=frac{a[j]}{sum}*frac{a[i]}{sum+d}$

    显然,$P1=P2=frac{a[i]*a[j]}{sum*(sum+d)}$,得证。

    然后写代码的时候还要注意一点就是那个概率的数字可能会很大,所以要先分解质因数约分一下。

    【代码实现】

     1 #include<bits/stdc++.h>
     2 #define go(i,a,b) for(register int i=a;i<=b;i++)
     3 #define back(i,a,b) for(register int i=a;i>=b;i--)
     4 #define ll long long
     5 using namespace std;
     6 int fr(){
     7     int w=0,q=1;
     8     char ch=getchar();
     9     while(ch>'9'||ch<'0'){
    10         if(ch=='-') q=-1;
    11         ch=getchar();
    12     }
    13     while(ch>='0'&&ch<='9')
    14         w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
    15     return w*q;
    16 }
    17 int prime[20002],num=0;
    18 int t,n,d;
    19 int a[1002],sum,ans1[20002],ans2[20002];
    20 int A1[20002],A2[20002];
    21 void Prime(){//找质数
    22     int v[20002];
    23     memset(v,0,sizeof(v));
    24     go(i,2,20000){
    25         if(!v[i]) v[i]=i,prime[++num]=i;
    26         go(j,1,num){
    27             if(i*prime[j]>20000||prime[j]>v[i]) break;
    28             v[i*prime[j]]=prime[j];
    29         }
    30     }
    31     return;
    32 }
    33 void yue(int *ans,int x){//约分
    34     go(i,1,num){
    35         if(x<prime[i])break;
    36         while(x%prime[i]==0)
    37             ans[i]++,x/=prime[i];
    38     }
    39     return;
    40 }
    41 void add(int *ans,int x,int &len){
    42     go(i,1,len) ans[i]*=x;
    43     go(i,1,len) ans[i+1]+=ans[i]/10,ans[i]%=10;
    44     while(ans[len+1])
    45         len++,ans[len+1]+=ans[len]/10,ans[len]%=10;
    46     return;
    47 }
    48 void mul(int *ans,int *x,int &len){//把约分后的数乘起来
    49     go(i,1,num)
    50         while(x[i]) add(ans,prime[i],len),x[i]--;
    51     return;
    52 }
    53 int main(){
    54     t=fr();n=fr();d=fr();
    55     go(i,1,t) a[i]=fr(),sum+=a[i];
    56     Prime();
    57     go(i,1,n){
    58         int y=fr();y=fr();
    59         if(!a[y]){printf("0/1");return 0;}
    60         yue(ans1,a[y]);yue(ans2,sum);sum+=d;a[y]+=d;
    61     }
    62     go(i,1,num){
    63         int cut=min(ans1[i],ans2[i]);
    64         ans1[i]-=cut;ans2[i]-=cut;
    65     }
    66     A1[1]=A2[1]=1;int len1=1,len2=1;
    67     mul(A1,ans1,len1);mul(A2,ans2,len2);
    68     back(i,len1,1) printf("%d",A1[i]);
    69     printf("/");
    70     back(i,len2,1) printf("%d",A2[i]);
    71     return 0;
    72 }
    代码戳这里
  • 相关阅读:
    tp 30秒超时
    zend studio git 提示错误
    php连接数据库
    php点击排序
    表情符号解析
    js Object.assign 方法
    Web界面简繁体转换
    H5骨架屏实战
    JavaScript heap out of memory问题
    Vue bus插件封装
  • 原文地址:https://www.cnblogs.com/THWZF/p/10699975.html
Copyright © 2011-2022 走看看