# 【LOJ#575】【LNR#2】不等关系（容斥，动态规划，分治FFT）

LOJ

## 题解

$f[i][j]=\sum_{k=0}^{i-1}f[k][j-1]*{n-s[k]\choose s[i]-s[k]}$

$f[i]=-\sum_{k=0}^{i-1}f[k]{n-s[k]\choose s[i]-s[k]}$

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MOD 998244353
#define MAX 524288
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int fpow(int a,int b){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;}
int W[MAX],r[MAX];
void NTT(int *P,int opt,int len)
{
int N,l=0;for(N=1;N<len;N<<=1)++l;
for(int i=0;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
for(int i=0;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
for(int i=1;i<N;i<<=1)
{
int w=fpow(3,(MOD-1)/(i<<1));W[0]=1;
for(int k=1;k<i;++k)W[k]=1ll*W[k-1]*w%MOD;
for(int j=0,p=i<<1;j<N;j+=p)
for(int k=0;k<i;++k)
{
int X=P[j+k],Y=1ll*W[k]*P[i+j+k]%MOD;
P[j+k]=(X+Y)%MOD;P[i+j+k]=(X+MOD-Y)%MOD;
}
}
if(opt==-1)
{
reverse(&P[1],&P[N]);
for(int i=0,inv=fpow(N,MOD-2);i<N;++i)P[i]=1ll*P[i]*inv%MOD;
}
}
int jc[MAX],jv[MAX],inv[MAX];
int n,a[MAX],ans,cnt;char s[MAX];
bool book[MAX];
int A[MAX],B[MAX],f[MAX];
void CDQ(int l,int r)
{
if(l==r)
{
if(l==0)f[l]=1;
else if(!book[l])f[l]=0;
else f[l]=1ll*f[l]*(MOD-jv[n-l])%MOD;
return;
}
int mid=(l+r)>>1;
CDQ(l,mid);
for(int i=l;i<=mid;++i)A[i-l]=1ll*f[i]*jc[n-i]%MOD;
for(int i=1;i<=r-l+1;++i)B[i]=jv[i];
int N;for(N=1;N<=r-l+1+mid-l+1;N<<=1);
NTT(A,1,N);NTT(B,1,N);
for(int i=0;i<N;++i)A[i]=1ll*A[i]*B[i]%MOD;
NTT(A,-1,N);
for(int i=mid+1;i<=r;++i)f[i]=(f[i]+A[i-l])%MOD;
for(int i=0;i<N;++i)A[i]=B[i]=0;
CDQ(mid+1,r);
}
int C(int n,int m){if(n<0||m<0||n<m)return 0;return 1ll*jc[n]*jv[m]%MOD*jv[n-m]%MOD;}
int main()
{
scanf("%s",s+1);n=strlen(s+1)+1;
for(int i=1;i<n;++i)if(s[i]=='>')book[i]=true,++cnt;
inv[0]=inv[1]=jc[0]=jv[0]=1;
for(int i=2;i<=n;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=n;++i)jc[i]=1ll*jc[i-1]*i%MOD;
for(int i=1;i<=n;++i)jv[i]=1ll*jv[i-1]*inv[i]%MOD;
CDQ(0,n);
/*
f[0]=1;
for(int i=1;i<=n;++i)
if(book[i])
for(int j=0;j<i;++j)
f[i]=(f[i]+MOD-1ll*f[j]*C(n-j,i-j)%MOD)%MOD;
*/
for(int i=0;i<=n;++i)ans=(ans+f[i])%MOD;
if(cnt&1)ans=(MOD-ans)%MOD;
printf("%d\n",ans);
return 0;
}

posted @ 2019-07-08 09:12  小蒟蒻yyb  阅读(474)  评论(0编辑  收藏