1. 程式人生 > >2018年8月16日暑假訓練日記

2018年8月16日暑假訓練日記

  賓館租期到了,早上打理了一下宿舍的事兒。

  下午很難受的暴零了,大佬做出來個區間dp,我現學了期望dp,然後寫了個期望dp超時了,要是m變成原來的一半就過了,正好卡死了,然後搞了一發假dp,還是不是很理解區間dp,所以失敗了。

#include<iostream>

#include<cstring>

#include<cmath>

#include<cstdio>

#include<algorithm>

#define mo 1000000007

using namespace std;

long long a[1010];

long

long b[1010];

long long p[1010];

long long ip[1010];

long long l[1010][1010];

long long ans[1010];

long long qpow(long long x,long long y){

long long ans=1;

long long k=x;

while(y){

if(y&1)ans=ans*k%mo;

k=k*k%mo;

y>>=1;

}

return (ans+mo)%mo;

}

void get(){

long long i;

a[0]=1;

b[0]=1;

a[1]=1;

b[1]=1;

for (i=2;i<1010;i++){

a[i]=((a[i-1]*i)%mo+mo)%mo;

b[i]=(qpow(a[i],mo-2)+mo)%mo;

}

}

long long zuhe(long long n,long long m){

if (n<m||m<0) return 0;

return  a[n]*b[m]%mo*b[n-m]%mo;

}

int main(){

long long n,m;

long long i,j,k;

get();

while (scanf("%lld%lld",&n,&m)!=EOF){

long long temp=qpow(100,mo-2);

for (i=1;i<=n;i++){

scanf("%lld",&p[i]);

p[i]=p[i]*temp%mo;

for (j=1;j<=m-1;j++){

l[i][j]=(l[i-1][j]+1)%mo;

for (k=1;k<=j-1;k++){

l[i][j]=(l[i][j]+zuhe(j,k)*l[i-1][k]%mo)%mo;

}

l[i][j]=l[i][j]*p[i]%mo;

}

long long temp=1;

for (j=1;j<=m-1;j++){

temp=(temp+zuhe(m,j)*l[i-1][j]%mo)%mo;

}

ans[i]=(ans[i-1]+p[i]*temp%mo)%mo;

}

printf("%lld\n",(ans[n]+mo)%mo);

}

}

  而正解相當於對區間的一個列舉,對每個區間為全1的情況進行了一個概率列舉,就相當於裡面全都為1,兩頭為0的情況,一開始有點這個想法,但總覺的這樣會有重複,這個操作可有夠厲害的。