1. 程式人生 > >bzoj5342 CTSC2018 Day1T3 青蕈領主

bzoj5342 CTSC2018 Day1T3 青蕈領主

pen AS swa define min aps 分享 main fft

首先顯然的是,題中所給出的n個區間要麽互相包含,要麽相離,否則一定不合法。

然後我們可以對於直接包含的關系建出一棵樹,於是現在的問題就是給n個節點分配權值,使其去掉最後一個點後不存在非平凡(長度大於1)的連續區間。

我們發現這個方案數和不存在不經過最大(小)值的非平凡連續區間的排列數是等價的。

於是我們考慮$f[n]$為長度為$n+1$的答案,我們考慮去掉最小值。

如果合法,那麽必然是$f[n-1]$中的一種情況,而這時我們要將最小值插進去,我們發現,只要不插在次小值旁邊就都是合法的,於是這部分的貢獻就是$(n-1) \cdot f[n-1]$。

否則,我們考慮去掉後的序列中的極長的不經過最大值的非平凡連續區間長度為i,我們現在要將最小值插進去,然後滿足這裏面離散後沒有一個不經過最小值的非平凡連續區間,這是$f[i]$,然後這段區間權值的取值可以取遍$3~n$,就有$n-i-1$種方案,然後我們把他縮成一個點,現在要剩下的點合法,就是$f[n-i]$,這部分的貢獻就是$\sum_{i=2}^{n-2}{f[i] \cdot f[n-i] \cdot (i-1)}$

然後就可以愉快的cdq+fft啦。

技術分享圖片
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #define mod 998244353
 7 #define N 133333
 8 using namespace std;
 9 int f[N],T,n,l[N],q[N],top,ans,cnt,flag;
10 int len,inv,rev[N],a[N],b[N],tmp1[N],tmp2[N];
11 int qp(int a,int b){ 12 int c=1; 13 for(;b;b>>=1,a=1ll*a*a%mod) 14 if(b&1)c=1ll*c*a%mod; 15 return c; 16 } 17 void UPD(int &a,int b){a=(a+b>=mod)?(a+b-mod):(a+b);} 18 void ntt(int *a,int o){ 19 register int i,j,k,dan,now,t; 20 for(i=0;i<len;i++)if
(i<rev[i])swap(a[i],a[rev[i]]); 21 for(k=2;k<=len;k<<=1){ 22 dan=qp(3,o==1?(mod-1)/k:(mod-1-(mod-1)/k)); 23 for(i=0;i<len;i+=k){ 24 now=1; 25 for(j=0;j<(k>>1);j++,now=1ll*now*dan%mod){ 26 t=1ll*a[i+j+(k>>1)]*now%mod; 27 a[i+j+(k>>1)]=(a[i+j]-t+mod)%mod; 28 a[i+j]=(a[i+j]+t)%mod; 29 } 30 } 31 } 32 if(o==-1){for(i=0;i<len;i++)a[i]=1ll*a[i]*inv%mod;} 33 } 34 void mul(int *a,int *b,int *c,int l1,int l2){ 35 for(len=1;len<=l1+l2;len<<=1); 36 for(int i=0;i<len;i++){ 37 if(i&1)rev[i]=(rev[i>>1]>>1)|(len>>1); 38 else rev[i]=rev[i>>1]>>1; 39 } 40 inv=qp(len,mod-2); 41 for(int i=0;i<l1;i++)tmp1[i]=a[i]; 42 for(int i=l1;i<len;i++)tmp1[i]=0; 43 for(int i=0;i<l2;i++)tmp2[i]=b[i]; 44 for(int i=l2;i<len;i++)tmp2[i]=0; 45 ntt(tmp1,1);ntt(tmp2,1); 46 for(int i=0;i<len;i++)c[i]=1ll*tmp1[i]*tmp2[i]%mod; 47 ntt(c,-1); 48 } 49 void cdq(int l,int r){ 50 if(l==r){ 51 UPD(f[l],1ll*f[l-1]*(l-1)%mod); 52 return ; 53 } 54 int mid=(l+r)>>1; 55 cdq(l,mid); 56 for(int i=l;i<=mid;i++){ 57 a[i-l]=1ll*f[i]*(i-1)%mod; 58 b[i-l]=f[i]; 59 } 60 mul(a,b,a,mid-l+1,mid-l+1); 61 for(int i=max(l<<1,mid+1);i<=r;i++) 62 UPD(f[i],a[i-(l<<1)]); 63 if(l!=2){ 64 for(int i=2;i<=min(l-1,r-l);i++)a[i-2]=f[i]; 65 for(int i=l;i<=mid;i++)b[i-l]=f[i]; 66 mul(a,b,a,min(l-1,r-l)-1,mid-l+1); 67 for(int i=max(l+2,mid+1);i<=r;i++) 68 UPD(f[i],1ll*a[i-l-2]*(i-2)%mod); 69 } 70 cdq(mid+1,r); 71 } 72 int main(){ 73 scanf("%d%d",&T,&n); 74 f[0]=1;f[1]=2; 75 cdq(2,n-1); 76 while(T--){ 77 ans=1;top=0; 78 for(int i=1;i<=n;i++) 79 scanf("%d",&l[i]); 80 if(l[n]!=n){puts("0");continue;} 81 for(int i=1;i<=n;i++){ 82 cnt=flag=0; 83 while(top&&i-l[i]+1<=q[top]){ 84 if(i-l[i]+1>q[top]-l[q[top]]+1){flag=1;break;} 85 top--,cnt++; 86 } 87 if(flag==1)break; 88 ans=1ll*ans*f[cnt]%mod; 89 q[++top]=i; 90 } 91 if(flag)puts("0"); 92 else printf("%d\n",ans); 93 } 94 }
View Code

bzoj5342 CTSC2018 Day1T3 青蕈領主