「LibreOJ NOI Round #2」不等關係

主席花費1sec秒的題,我看着主席的題解想了一年。。

鏈接:https://loj.ac/problem/575

考慮容斥其中大於或小於其中一個限制,推式子,然後上分治fft優化。

具體的Orz主席https://www.cnblogs.com/Mr-Spade/p/11115654.html

附對着主席題解的蒟蒻學習筆記:

代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+100,M=N*8;
const ll mod=998244353;

int n,bl[N];
ll f[N],fac[N],ifac[N];
bool a[N];
char S[N];

ll qpow(ll x,ll y=mod-2)
{
	ll res=1;
	while(y)
	{
		if(y&1)res=res*x%mod;
		x=x*x%mod,y>>=1;
	}
	return res;
}
inline ll Add(ll x,ll y)
{return (x+y)%mod;}
inline ll Sub(ll x,ll y)
{return (x-y+mod)%mod;}
inline ll Mul(ll x,ll y)
{return x*y%mod;}
inline ll div(ll x,ll y)
{return x*qpow(y)%mod;}

ll F[M],G[M];
int wh[M],len,cc;
void ntt(ll *a,bool inv)
{
	for(int i=0;i<len;i++)
		if(i<wh[i])swap(a[i],a[wh[i]]);
	ll tp,mo,ha;
	for(int l=2,md;l<=len;l<<=1)
	{
		md=l>>1,tp=qpow(3,(mod-1)/l);
		for(int i=0;i<len;i+=l)
		{
			mo=1;
			for(int j=0;j<md;j++,mo=Mul(mo,tp))
			{
				ha=Mul(a[i+j+md],mo);
				a[i+j+md]=Sub(a[i+j],ha);
				a[i+j]=Add(a[i+j],ha);
			}
		}
	}
	if(inv)
	{
		tp=qpow(len);
		for(int i=1;i<len/2;i++)swap(a[i],a[len-i]);
		for(int i=0;i<len;i++)a[i]=Mul(a[i],tp);
	}
}

void pre_ntt(int le)
{
	cc=0,len=1;
	while(len<=le)len<<=1,++cc;
	for(int i=1;i<len;i++)
		wh[i]=(wh[i>>1]>>1)|((i&1)<<(cc-1));
	for(int i=0;i<len;i++)F[i]=G[i]=0;
}

void sol(int l,int r)
{
	if(l==r)
	{
		if(l==0)return;
		if(bl[l]==1)f[l]=mod-f[l];
		return;
	}
	int mid=(l+r)>>1;
	sol(l,mid);
	pre_ntt(r-l+mid-l);
	for(int i=l;i<=mid;i++)
		F[i-l]=Mul(f[i],Mul(a[i],bl[i]));
	for(int i=1;i<=r-l;i++)
		G[i]=ifac[i];
	ntt(F,0),ntt(G,0);
	for(int i=0;i<len;i++)F[i]=Mul(F[i],G[i]);
	ntt(F,1);
	for(int i=mid+1;i<=r;i++)
		f[i]=Add(f[i],F[i-l]);
	sol(mid+1,r);
}

int main()
{
	//freopen("37.txt","r",stdin);
	fac[0]=1;
	for(int i=1;i<N;i++)
		fac[i]=Mul(fac[i-1],i);
	ifac[N-1]=qpow(fac[N-1]);
	for(int i=N-2;i>=0;i--)
		ifac[i]=Mul(ifac[i+1],i+1);
	scanf("%s",S+1);
	n=strlen(S+1);
	a[0]=1;
	for(int i=1;i<=n;i++)
	{
		if(S[i]=='>')a[i]=1;
		else a[i]=0;
	}
	ll nw=mod-1;
	for(int i=1;i<=n;i++)
	{
		bl[i]=nw;
		if(S[i]=='>')nw=mod-nw;
	}
	bl[0]=1,bl[n+1]=nw,f[0]=1;
	sol(0,n+1);
	printf("%lld\n",Mul(f[n+1],fac[n+1]));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章