【NOI2017】泳池
题解:
满分的笛卡尔树以后再学吧。。
40分还是比较好想的
但是状态挺复杂的
直接贴代码了
代码:
#include <bits/stdc++.h> using namespace std; #define ll long long #define IL inline #define rint register ll #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) #define me(x) memset(x,0,sizeof(x)) ll n,k,x,y; ll mo=998244353; ll f[2][11][6][4][3][3][2][2]; ll ans=0; void js(ll &x,ll y) { x=(x+y)%mo; } void gcd(ll x,ll y,ll &a,ll &b) { if (y==0) { a=1; b=0; return; } gcd(y,x%y,b,a); b=b-a*(x/y); } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); cin>>n>>k>>x>>y; ll x1,y1; gcd(y,mo,x1,y1); ll pp=(x*x1)%mo; int p[2000]; p[0]=1; rep(i,1,k) p[i]=(p[i-1]*pp)%mo; rep(i,0,k) p[i]=(p[i]*(1ll-pp))%mo; if (n==1) { cout<<(p[k]%mo+mo)%mo<<endl; return 0; } f[0][0][0][0][0][0][0][0]=1; rep(i,1,n) { ll kk=i%2,tt=(i+1)%2; me(f[kk]); rep(i,0,k) { rep(i1,0,k) { if ((i1+(i>=1))>k) break; rep(j1,0,k/2) { if ((j1+(i>=2))*2>k) break; rep(i2,0,k/3) { if ((i2+(i>=3))*3>k) break; rep(j2,0,k/4) { if ((j2+(i>=4))*4>k) break; rep(i3,0,k/5) { if ((i3+(i>=5))*5>k) break; rep(j3,0,1) { if (j3==1&&i>=6) break; rep(k1,0,1) { bool t=0; if ((i1+(i>=1))==k) t=1; if ((j1+(i>=2))*2==k) t=1; if ((i2+(i>=3))*3==k) t=1; if ((j2+(i>=4))*4==k) t=1; if ((i3+(i>=5))*5==k) t=1; if (i==k) t=1; js(f[kk][(i>=1)?i1+1:0][(i>=2)?j1+1:0][(i>=3)?i2+1:0][(i>=4)?j2+1:0][(i>=5)?i3+1:0][i>=6][k1|t], f[tt][i1][j1][i2][j2][i3][j3][k1]*p[i]); int ans1=3; ans1++; } } } } } } } } } rep(i1,0,10) rep(j1,0,5) rep(i2,0,3) rep(j2,0,2) rep(i3,0,2) rep(j3,0,1) js(ans,f[n%2][i1][j1][i2][j2][i3][j3][1]); cout<<(ans%mo+mo)%mo<<endl; return 0; }