• [补档]弱题


    弱题

    题目

    有M个球,一开始每个球均有一个初始标号,标号范围为1~N且为整数,标号为i的球有ai个,并保证Σai = M。
    每次操作等概率取出一个球(即取出每个球的概率均为1/M),若这个球标号为k(k < N),则将它重新标号为k + 1;若这个球标号为N,则将其重标号为1。(取出球后并不将其丢弃)
    现在你需要求出,经过K次这样的操作后,每个标号的球的期望个数。

    INPUT

    第1行包含三个正整数N,M,K,表示了标号与球的个数以及操作次数。
    第2行包含N个非负整数ai,表示初始标号为i的球有ai个。

    OUTPUT

    应包含N行,第i行为标号为i的球的期望个数,四舍五入保留3位小数

    SAMPLE

    INPUT

    2 3 2
    3 0

    OUTPUT

    1.667
    1.333

    解题报告

    弱题一点都不弱好吧= =,这题考试时打了个暴力,连不带优化的矩阵快速幂都没想出来= =
    正解:
    设f[i][j]表示第i个时间段,第j种的期望数量。
    首先,我们可以轻松地得到一个递推式子:

      f[i][j]=f[i-1][j-1]/m-f[i-1][j]+f[i-1][j]


    正确性是很显然的,因为当前这个状态是由前一个转移过来,自己转移出去以及原来就有的数得到的,继续由一个高(ji)深(ben)的数学定理——乘法分配律可以得到:

      f[i][j]=(m-1)/m*f[i-1][j]+f[i-1][j-1]/m


    那么显然,f[i][j]只与f[i-1]时的状态有关,那么显然我们可以去掉一维,从而得到一个极其简单的递推关系,就可以用矩阵快速幂来优化啦。
    我们自然可以构造出这样一个矩阵(以3*3为例):
    但是显然普通的矩阵快速幂的复杂度是O(n³logk),会炸,所以我们需要优化。
    那么显然我们可以观察到,该矩阵的每一行,都可以由第一行平移得到,那么我们只需要维护第一行,便可推出整个矩阵,从而将复杂度将为O(能过) O(n²logk)
     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 using namespace std;
     5 inline int read(){
     6     int sum(0);
     7     char ch(getchar());
     8     for(;ch<'0'||ch>'9';ch=getchar());
     9     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
    10     return sum;
    11 }
    12 int n,m,k;
    13 double a[1001][1001],b[1001];
    14 double tmp[1001];
    15 inline void multi_self(){
    16     memset(tmp,0,sizeof(tmp));
    17     for(int i=1;i<=n;i++)
    18         for(int j=1;j<=n;j++)
    19             tmp[i]+=a[1][j]*a[j][i];
    20     for(int i=1;i<=n;i++)
    21         a[1][i]=tmp[i];
    22     for(int i=2;i<=n;i++){
    23         for(int j=2;j<=n;j++)
    24             a[i][j]=a[i-1][j-1];
    25         a[i][1]=a[i-1][n];
    26     }
    27 }
    28 inline void multi_ea(){
    29     memset(tmp,0,sizeof(tmp));
    30     for(int i=1;i<=n;i++)
    31         for(int j=1;j<=n;j++)
    32             tmp[i]+=b[j]*a[i][j];
    33     for(int i=1;i<=n;i++)
    34         b[i]=tmp[i];
    35 }
    36 int main(){
    37 //  freopen("data.in","r",stdin);
    38 //  freopen("data.out","w",stdout);
    39     n=read(),m=read(),k=read();
    40     for(int i=1;i<=n;i++){
    41         int x(read());
    42         b[i]=x*1.0;
    43     }
    44     a[1][1]=(double)(m-1)/(double)m;
    45     a[1][n]=1.0/(double)m;
    46     for(int i=2;i<=n;i++)
    47         a[i][i-1]=1.0/(double)m,a[i][i]=(double)(m-1)/(double)m;
    48     while(k){
    49         if(k&1)
    50             multi_ea();
    51         multi_self();
    52         k>>=1;
    53     }
    54     for(int i=1;i<=n;i++)
    55         printf("%.3lf
    ",b[i]);
    56 }
    View Code
  • 相关阅读:
    AS快捷键的设置
    hausaufgabe--python 23- Recurse 2
    hausaufgabe--python 22- Recurse
    hausaufgabe--python 21_ Lambda
    hausaufgabe--python 20-Closure functions 2
    hausaufgabe--python 20- usage of Closure
    hausaufgabe--python 19- Functions 2
    hausaufgabe--python 18- Defined specific Functions
    hausaufgabe--python 17- Function definition
    hausaufgabe--python 16- Sequenz
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7276961.html
Copyright © 2020-2023  润新知