LOJ575 「LibreOJ NOI Round #2」不等关系

Link
若忽略掉>的限制,那么问题等价于将\(1,\cdots,n\)填入若干个长度为\(a_1,\cdots,a_m\)的递增序列,方案数为\(\frac{n!}{\prod a_i!}\)
>可以用容斥来计算,考虑把这个容斥的过程写成dp,设\(i!f_i\)\(pre(i)\)的合法排列数,那么我们有

\[f_0=1,f_i=\sum\limits_{j=0}^{i-1}[s_j\ne<](-1)^{cnt_{i-1}-cnt_j}f_j\frac1{(i-j)!} \]

其中\(cnt_i\)\(pre(i)\)>的出现次数。分治FFT即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
using i64=long long;
const int N=1<<18,P=998244353;
char str[N];int len,rev[N],cnt[N];i64 fac,w[N],ifac[N],f[N];
void inc(i64&a,i64 b){a+=b-P,a+=a>>63&P;}
void dec(i64&a,i64 b){a-=b,a+=a>>63&P;}
i64 pow(i64 a,int b){i64 r=1;for(;b;b>>=1,a=a*a%P)if(b&1)r=r*a%P;return r;}
int getlen(int n){return 1<<(32-__builtin_clz(n));}
void init(int n)
{
    int lim=1<<(len=32-__builtin_clz(n)),pos=lim/2;i64 g=pow(3,(P-1)/lim);
    for(int i=1;i<lim;++i) rev[i]=(rev[i>>1]>>1)|(i&1? pos:0);
    w[pos]=1;for(int i=pos+1;i<lim;++i) w[i]=g*w[i-1]%P;
    for(int i=pos-1;i;--i) w[i]=w[i<<1];
    fac=1;for(int i=1;i<=n;++i) fac=i*fac%P;
    ifac[n]=pow(fac,P-2);for(int i=n;i;--i) ifac[i-1]=i*ifac[i]%P;
}
void NTT(i64*a,int lim,int f)
{
    if(!~f) std::reverse(a+1,a+lim);
    for(int i=0,x=len-__builtin_ctz(lim);i<lim;++i) if(i<rev[i]>>x) std::swap(a[i],a[rev[i]>>x]);
    for(int i=1;i<lim;i<<=1) for(int j=0,d=i<<1;j<lim;j+=d) for(int k=0,x;k<i;++k) x=w[i+k]*a[i+j+k]%P,dec(a[i+j+k]=a[j+k],x),inc(a[j+k],x);
    if(!~f) for(int i=0,x=P-(P-1)/lim;i<lim;++i) a[i]=x*a[i]%P;
}
void solve(int l,int r)
{
    static i64 a[N],b[N];
    if(l==r) return f[l]=!l? 1:str[l]=='<'? 0:cnt[l-1]&1? P-f[l]:f[l],void();
    int mid=(l+r)/2,lim=getlen(r-l+1);solve(l,mid);
    memset(a,0,8*lim),memset(b,0,8*lim),memcpy(b+1,ifac+1,8*(r-l));
    for(int i=l;i<=mid;++i) a[i-l]=cnt[i]&1? P-f[i]:f[i];
    NTT(a,lim,1),NTT(b,lim,1);
    for(int i=0;i<lim;++i) a[i]=a[i]*b[i]%P;
    NTT(a,lim,-1);
    for(int i=mid+1;i<=r;++i) inc(f[i],a[i-l]);
    solve(mid+1,r);
}
int main()
{
    scanf("%s",str+1);int n=strlen(str+1)+1;init(n);
    for(int i=1;i<=n;++i) cnt[i]=cnt[i-1]+(str[i]=='>');
    solve(0,n),printf("%lld",fac*f[n]%P);
}
posted @ 2020-06-04 09:41  Shiina_Mashiro  阅读(287)  评论(0编辑  收藏  举报