列表

详情


NC207748. 划分

描述

tacmon有两个长度都为的序列
他现在要用这两个序列构造另一个长度为的序列,满足:

请你求出有多少种构造方案,答案对取模。

输入描述

第一行一个整数N。

第二行有2N个整数,表示

第三行有2N个整数,表示

输出描述

输出一行一个整数,表示答案对998244353取模的结果。

示例1

输入:

3
1 2 3 4 5 6
2 3 4 5 6 7

输出:

20

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++11) 解法, 执行用时: 2253ms, 内存消耗: 55056K, 提交时间: 2020-11-28 20:34:25

#include<algorithm>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<vector>
#define rep(i,x,y) for(int i=x; i<=y; ++i)
#define repd(i,x,y) for(int i=x; i>=y; --i)
#define mid (l+r>>1)
#define pb push_back

using namespace std;
const int N=50005,mod=998244353;
typedef long long LL;
int n,a[2][N<<1],len,bin[N<<2];
LL ans,A[N<<2],B[N<<2],Wn[19][1<<19];
vector <LL> tmp[2][2],vt[2][2][N<<1];

int getint()
{
	char ch;
	while(!isdigit(ch=getchar()));
	int x=ch-48;
	while(isdigit(ch=getchar())) x=x*10+ch-48;
	return x;
}

LL getmi(LL a,LL x)
{
	LL rt=1;
	while(x)
	{
		if(x&1) rt=rt*a%mod;
		a=a*a%mod,x>>=1;
	}
	return rt;
}

void FFT(LL a[],int len,int tp)
{
	rep(i,0,len-1) bin[i]=bin[i>>1]>>1|((i&1)*(len>>1));
	rep(i,0,len-1) if(i<bin[i]) swap(a[i],a[bin[i]]);
	for(int i=1,cnt=0; i<len; ++cnt,i<<=1)
	{
		for(int j=0; j<len; j+=i<<1)
		{
			LL w=0,x,y;
			rep(k,0,i-1)
			{
				x=a[j+k],y=a[i+j+k]*Wn[cnt][w+i],w+=tp;
				a[j+k]=(x+y)%mod,a[i+j+k]=(x-y)%mod;
			}
		}
	}
	if(tp==-1)
	{
		LL x=getmi(len,mod-2);
		rep(i,0,len-1) a[i]=a[i]*x%mod;
	}
}

void inc(LL &x,LL y)
{
	if((x+=y)>=mod) x-=mod;
}

void mul(vector <LL> &a,vector <LL> &b,vector <LL> &c)
{
	int sz1=b.size()-1;
	int sz2=c.size()-1;
	for(len=1; len<=sz1+sz2; len<<=1);
	rep(i,0,len-1) A[i]=B[i]=0;
	rep(i,0,sz1) A[i]=b[i];
	rep(i,0,sz2) B[i]=c[i];
	FFT(A,len,1),FFT(B,len,1);
	rep(i,0,len-1) A[i]=A[i]*B[i]%mod;
	FFT(A,len,-1);
	int sz=a.size()-1;
	rep(i,0,min(n,sz1+sz2))
	{
		if(i<=sz) inc(a[i],A[i]);
		else a.pb(A[i]);
	}
}

void solve(int l,int r)
{
	if(l==r)
	{
		rep(i,0,1) rep(j,0,1) vt[i][j][l].clear();
		vt[1][1][l].pb(0),vt[1][1][l].pb(1),vt[0][0][l].pb(1);
		return;
	}
	solve(l,mid),solve(mid+1,r);
	rep(i,0,1) rep(j,0,1) tmp[i][j].clear();
	rep(i,0,1) rep(j,0,1) rep(_i,0,1) rep(_j,0,1) if(a[j][mid]<=a[_i][mid+1])
		mul(tmp[i][_j],vt[i][j][l],vt[_i][_j][mid+1]);
	rep(i,0,1) rep(j,0,1) vt[i][j][l]=tmp[i][j];
}	

LL query(vector <LL> &a,int x)
{
	int sz=a.size()-1;
	if(x<=sz) return a[x];
	return 0;
}

int main()
{
	n=getint();
	rep(i,1,2*n) a[1][i]=getint();
	rep(i,1,2*n) a[0][i]=getint();
	rep(i,0,18)
	{
		int x=1<<i;
		Wn[i][x]=1;
		LL wn=getmi(3,(mod-1)/(x<<1));
		rep(j,1,x-1) Wn[i][j+x]=Wn[i][j+x-1]*wn%mod;
		wn=getmi(wn,mod-2);
		rep(j,1,x-1) Wn[i][-j+x]=Wn[i][-j+x+1]*wn%mod;
	}
	solve(1,2*n);
	rep(i,0,1) rep(j,0,1) ans=(ans+query(vt[i][j][1],n))%mod;
	printf("%lld\n",(ans+mod)%mod);
	return 0;
}

上一题