zoukankan      html  css  js  c++  java
  • 弱题(循环矩阵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 }
    循环矩阵留坑)
  • 相关阅读:
    服务器状态码
    QuerySet中添加Extra进行SQL查询
    django配置一个网站建设
    MySQL数据库查询中的特殊命令
    125. Valid Palindrome
    121. Best Time to Buy and Sell Stock
    117. Populating Next Right Pointers in Each Node II
    98. Validate Binary Search Tree
    91. Decode Ways
    90. Subsets II
  • 原文地址:https://www.cnblogs.com/FOXYY/p/7257627.html
Copyright © 2011-2022 走看看