LOJ#2304. 「NOI2017」泳池

$n \leq 1e9$底边长的泳池,好懒啊泥萌自己看题吧,$k \leq 1000$。答案对998244353取膜。

现在令$P$为安全,$Q$为危险的概率。刚好$K$是极其不好算的,于是来算$\leq K$,然后用$calc(K)-calc(K-1)$解决。$f(i,j)$--$i$行$j$列的矩形中,第$i$行有危险,前$i-1$行都没有危险,而最大矩形$\leq K$的概率,枚举最后一个危险格递推,$f(i,j)=\sum_{k=0}^{j-1}f(i,k)P^{i-1}Qg(i,j-k-1)$,其中$g(i,j)$表示$i$行$j$列矩形的前$i$行都没危险,而最大矩形$\leq K$的概率,就是$f$的一个前缀和。最后$h(i)$表示$i$列的答案,$h(i)=\sum_{j=i-K}^{i}h(j-1)*Q*g(1,i-j)$,注意一开始的$h(i)+=g(1,i)$。

然后就可以拿到70分。90分的话加个矩阵快速幂,100分加个多项式取膜。只写70.

 1 //#include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 //#include<math.h>
 5 //#include<set>
 6 //#include<queue>
 7 //#include<bitset>
 8 //#include<vector>
 9 #include<algorithm>
10 #include<stdlib.h>
11 using namespace std;
12 
13 #define LL long long
14 int qread()
15 {
16     char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
17     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
18 }
19 
20 //Pay attention to '-' , LL and double of qread!!!!
21 
22 int n,K,X,Y,P,Q;
23 const int mod=998244353;
24 int powmod(int a,int b)
25 {
26     int ans=1;
27     while (b) {if (b&1) ans=1ll*ans*a%mod; a=1ll*a*a%mod; b>>=1;}
28     return ans;
29 }
30 
31 #define maxn 1011
32 int f[maxn][maxn],g[maxn][maxn],h[maxn],pp[maxn],qq[maxn];
33 
34 int calc(int K)
35 {
36     memset(f,0,sizeof(f)); memset(g,0,sizeof(g));
37     for (int i=1;i<=K+1;i++) g[i][0]=1;
38     for (int i=K+1;i>1;i--)
39         for (int j=1,to=K/(i-1);j<=to;j++)
40         {
41             for (int k=0;k<j;k++)
42             {
43                 f[i][j]=(f[i][j]+1ll*f[i][k]*pp[i-1]%mod*Q%mod*g[i][j-k-1])%mod;
44                 f[i][j]=(f[i][j]+1ll*g[i][k]*pp[i-1]%mod*Q%mod*g[i][j-k-1])%mod;
45             }
46             g[i-1][j]=(g[i][j]+f[i][j])%mod;
47         }
48     memset(h,0,sizeof(h)); h[0]=1;
49     for (int i=1;i<=n;i++)
50     {
51         if (i<=K) h[i]=g[1][i];
52         for (int j=max(1,i-K);j<=i;j++)
53             h[i]=(h[i]+1ll*h[j-1]*Q%mod*g[1][i-j])%mod;
54     }
55     return h[n];
56 }
57 
58 int main()
59 {
60     n=qread(); K=qread(); X=qread(); Y=qread(); P=1ll*X*powmod(Y,mod-2)%mod; Q=(mod+1-P)%mod;
61     pp[0]=qq[0]=1; for (int i=1;i<=K;i++) pp[i]=pp[i-1]*1ll*P%mod,qq[i]=qq[i-1]*1ll*Q%mod;
62     printf("%d\n",(calc(K)-calc(K-1)+mod)%mod);
63     return 0;
64 }
View Code

 

posted @ 2018-06-23 13:43  Blue233333  阅读(150)  评论(0编辑  收藏  举报