zoukankan      html  css  js  c++  java
  • [CodeForces-708E]Student's Camp

    题目大意:
      一个n*m的墙,被吹k天风,每块靠边的砖都有p的概率被吹掉。
      如果上下两行没有直接相连的地方,我们则认为这一堵墙已经倒塌。
      问最后墙不倒塌的概率(模意义)。

    思路:
      动态规划。
      用f[i][j][k]表示到了第i层,只剩下j~k的砖头并且不倒塌的概率。
      则f[i][j][k]=sum{f[i-1][l][r]|[l,r]与[j,k]有交集}*这一层只剩[l,r]的概率。
      概率可以O(n)预处理,接下来要枚举i,j,k,l,r,所以是O(m^4n)的。
      接下来考虑预处理sum{f[i-1][l][r]|[l,r]与[j,k]有交集}。
      显然有交集的概率=总概率-没有交集的概率=总概率-r<i的概率-j<l的概率。
      而这些概率都可以一边转移一边推。
      这样转移的时候就不需要考虑具体的l,r,是O(m^2n)的。
      数组1500^3还会爆,考虑滚动数组,勉强开下,反正还是TLE。
      正解是一个很神奇的O(mn)算法。(并不是很懂)
      考虑用f[i][k]表示前面的f[i][1][k]~f[i][k][k]的和。
      然后预处理所有关于j的前缀和。
      然后递推式就只与i,k有关了。

     1 #include<cstdio>
     2 #include<cctype>
     3 typedef long long int64;
     4 inline int getint() {
     5     register char ch;
     6     while(!isdigit(ch=getchar()));
     7     register int x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x;
    10 }
    11 const int mod=1e9+7;
    12 const int N=1501,M=1501,K=100001;
    13 void exgcd(const int &a,const int &b,int &x,int &y) {
    14     if(!b) {
    15         x=1;
    16         y=0;
    17         return;
    18     }
    19     exgcd(b,a%b,y,x);
    20     y-=a/b*x;
    21 }
    22 inline int inv(const int64 &x) {
    23     int tmp,ret;
    24     exgcd(x,mod,ret,tmp);
    25     return (ret+mod)%mod;
    26 }
    27 int f[2][M];
    28 int p[K],q[K];
    29 int fact[K],tcaf[K];
    30 int k;
    31 inline int calc(const int &x) {
    32     return (int64)fact[k]*tcaf[k-x]%mod*tcaf[x]%mod*p[x]%mod*q[k-x]%mod;
    33 }
    34 int main() {
    35     int n=getint(),m=getint();
    36     int a=getint(),b=getint();
    37     k=getint();
    38     fact[0]=1;
    39     for(register int i=1;i<=k;i++) {
    40         fact[i]=(int64)fact[i-1]*i%mod;
    41     }
    42     tcaf[k]=inv(fact[k]);
    43     for(register int i=k-1;~i;i--) {
    44         tcaf[i]=(int64)tcaf[i+1]*(i+1)%mod;
    45     }
    46     p[0]=q[0]=1;
    47     p[1]=q[1]=inv(b);
    48     p[1]=(int64)p[1]*a%mod;
    49     q[1]=(int64)q[1]*(b-a)%mod; 
    50     for(register int i=2;i<=k;i++) {
    51         p[i]=(int64)p[i-1]*p[1]%mod;
    52         q[i]=(int64)q[i-1]*q[1]%mod;
    53     }
    54     f[0][m]=1;
    55     for(register int i=1;i<=n;i++) {
    56         int s1=0,s2=0;
    57         for(register int j=0;j<=m;j++) {
    58             f[i&1][j]=((int64)s1*(f[!(i&1)][m]-f[!(i&1)][m-j])-s2)%mod*calc(m-j)%mod;
    59             s1=(s1+calc(j))%mod;
    60             s2=(s2+(int64)f[!(i&1)][j]*calc(j))%mod;
    61         }
    62         for(register int j=1;j<=m;j++) {
    63             f[i&1][j]=(f[i&1][j]+f[i&1][j-1])%mod;
    64         }
    65     }
    66     printf("%d
    ",(f[n&1][m]+mod)%mod);
    67     return 0;
    68 }
  • 相关阅读:
    《小团团团队》第一次作业:团队亮相
    《代码敲不队》第六次作业:团队项目系统设计改进与详细设计
    《代码敲不队》第五次作业:项目需求分析改进与系统设计
    《代码敲不队》第四次作业:项目需求调研与分析
    《代码敲不队》第三次作业:团队项目的原型设计
    《代码敲不队》第二次作业:团队项目选题报告
    《代码敲不队》第一次作业:团队亮相
    《队长说得队》第六次作业:团队项目系统设计改进与详细设计
    《队长说得队》第五次作业:项目需求分析改进与系统设计
    《队长说得队》第四次作业:项目需求调研与分析
  • 原文地址:https://www.cnblogs.com/skylee03/p/7679922.html
Copyright © 2011-2022 走看看