• 弱题(循环矩阵1)


    问题 D: 弱题

    时间限制: 1 Sec  内存限制: 128 MB

    题目描述

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

    输入

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

    输出

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

    样例输入

    2 3 2
    3 0
     
    

    样例输出

    1.667
    1.333


    这道题很容易就能想到用矩阵快速幂,但n^3的时间复杂度显然是过不去,然后根据DP方程 f[i]=a/n*f[i-1]+(1-b/n)*f[i];所以每一项的转移都是从本位和前一位转移而来的,那么在构建出来的矩阵,无论自乘多少次都能地i+1行是由i行右移的得到的,最后一位到第一位;那么就可以用矩阵的第一行来表示整个矩阵,我实现的有些麻烦,我有把整个矩阵都重现了出来,其实可以直接由一个关系直接转移,还有进一步的优化空间;
      1 #include<cmath>
      2 #include<ctime>
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<iostream>
      7 #include<algorithm>
      8 using namespace std;
      9 int n,m,K;
     10 int num[1010];
     11 double f[1010];
     12 double a[1010][1010];
     13 double cc[1010];
     14 double b[1010][1010];
     15 void cheng1(){
     16     memset(cc,0,sizeof(cc));
     17     for(int i=1;i<=n;i++){
     18         for(int j=1;j<=n;j++){
     19             cc[i]+=b[j][i]*f[j];
     20         }
     21     }
     22     for(int i=1;i<=n;i++)
     23         f[i]=cc[i];
     24 }
     25 double dd[1010][1010];
     26 void cheng2(){
     27     memset(dd,0,sizeof(dd));
     28     for(int i=1;i<=n;i++){
     29         for(int j=1;j<=n;j++){
     30             dd[1][i]+=a[1][j]*a[j][i];
     31         }
     32     }
     33     for(int i=1;i<=n;i++)
     34         a[1][i]=dd[1][i];
     35     for(int i=2;i<=n;i++){
     36         for(int j=1;j<=n;j++){
     37             if(j==1){
     38                 a[i][j]=a[i-1][n];
     39                 continue;
     40             }
     41             a[i][j]=a[i-1][j-1];
     42         }
     43     }
     44 }
     45 void cheng3(){
     46     memset(dd,0,sizeof(dd));
     47     for(int i=1;i<=n;i++){
     48         for(int j=1;j<=n;j++){
     49             dd[1][i]+=a[1][j]*b[j][i];
     50             //if(i==1) cout<<"--->"<<a[1][j]<<"  "<<b[j][i]<<endl;
     51         }
     52     }
     53     for(int i=1;i<=n;i++){
     54         b[1][i]=dd[1][i];
     55     }
     56     for(int i=2;i<=n;i++){
     57         for(int j=1;j<=n;j++){
     58             if(j==1){
     59                 b[i][j]=b[i-1][n];
     60                 continue;
     61             }
     62             b[i][j]=b[i-1][j-1];
     63         }
     64     }
     65     //while(1);
     66 }
     67 int main(){
     68     //freopen("a.in","r",stdin);
     69 //  freopen("1.out","w",stdout);
     70     scanf("%d%d%d",&n,&m,&K);
     71     for(int i=1;i<=n;i++){
     72         scanf("%d",&num[i]);
     73         f[i]=num[i];
     74     }
     75     for(int i=1;i<=n;i++) b[i][i]=1;
     76     a[1][1]+=(double)(m-1)/m;
     77     a[n][1]+=(double)1/m;
     78     for(int i=2;i<=n;i++){
     79         a[i][i]+=(double)(m-1)/m;
     80         a[i-1][i]+=(double)1/m;
     81     }
     82     /*
     83     for(int i=1;i<=n;i++){
     84         for(int j=1;j<=n;j++){
     85             cout<<a[i][j]<<" ";
     86         }
     87         cout<<endl;
     88     }*/
     89     while(K){
     90         if(K&1){
     91             cheng3();
     92         }
     93         cheng2();
     94         K=K>>1;
     95     }
     96     cheng1();
     97     for(int i=1;i<=n;i++){
     98         printf("%.3lf
    ",f[i]);
     99     }
    100     return 0;
    101 }
    循环矩阵留坑)
  • 相关阅读:
    Visual C# 2008+SQL Server 2005 数据库与网络开发 12.4 自定义控件
    Visual C# 2008+SQL Server 2005 数据库与网络开发 13.1 菜单和菜单事件的创建
    Visual C# 2008+SQL Server 2005 数据库与网络开发 11.6 小结
    vs2005部署报表服务器项目老提示输入用户名密码解决办法
    Excel 文本处理常用函数
    使用APMServ时出现“1、Apache启动失败,请检查相关配置。√MySQL5.1已启动。”错误的终极解决办法:
    <img> 标签的border等属性尽量少用
    时间相减
    全面介绍 Netstat命令的使用技巧!
    apmserver中 mysql的root密码设定
  • 原文地址:https://www.cnblogs.com/FOXYY/p/7257627.html
Copyright © 2020-2023  润新知