列表

详情


NC50447. tokitsukaze and Another Protoss and Zerg

描述

还记得校赛的"Protoss and Zerg"吗?(https://ac.nowcoder.com/acm/contest/303/H)

这是另一个版本。

---------------以下为原题目描述(稍有修改)----------------

1v1,是星际争霸(StarCraft)中最常见的竞技模式。

tokitsukaze进行了n场1v1。在每一场的1v1中,她都有星灵(Protoss)和异虫(Zerg)两个种族可以选择,分别有a个单位和b个单位。因为tokitsukaze不太擅长玩人类(Terran),所以她肯定不会选择人类。

对于每一场1v1,玩家只能控制己方单位。也就是说,如果选择虫族,那么只能控制虫族单位,如果玩家选择星灵,那么只能控制星灵单位。

在n场1v1中,假设第i场,有ai个星灵单位,和bi个虫族单位。tokitsukaze可以在一场1v1中,任选一种种族进行游戏。如果选择了星灵,那么在这场游戏中,可以选择出兵1到ai个单位。那么同理,如果选择了虫族,那么在这场游戏中,可以选择出兵1到bi个单位。

假设所有星灵单位互不相同,所有异虫单位也互不相同,那么请问tokitsukaze打完这n场1v1,出兵的总方案数是多少。

注意:若两个方案,有其中一个单位不同,即视为不相同。

---------------以上为原题目描述(稍有修改)----------------

但是,tokitsukaze认为这个问题太简单了。

tokitsukaze想知道,恰好选择了0,1,2,3,...,个星灵单位的方案数分别是多少。由于答案很大,所以输出答案mod 998244353 后的结果。

数据保证

输入描述

第一行包括一个正整数n,(1≤n≤10^5)。
接下来一行有n个正整数a[i],(1≤a[i]≤2*10^5)。
接下来一行有n个正整数b[i],(1≤b[i]≤10^5)。
数据保证

输出描述

输出一行,个整数,用空格隔开,行末无多余的空格。

示例1

输入:

2
1 2
2 1

输出:

3 7 5 1

示例2

输入:

1
1
1

输出:

1 1

原站题解

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

C++(clang++ 11.0.1) 解法, 执行用时: 934ms, 内存消耗: 14712K, 提交时间: 2023-08-10 11:43:31

#include<bits/stdc++.h>
#define int long long
#define For(i,a,b) for(i=a;i<=b;i++)
#define FOR(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int N=6e5+10,mod=998244353,G=3,inv_G=332748118;
int fac[N],inv[N];
int a[N],b[N];
int qz(int x,int y){
	int res=1;
	for(;y;y>>=1){
		if(y&1) res=res*x%mod;
		x=x*x%mod;
	}
	return res;
}
void init(int n){
	int i;
	fac[1]=1;
	For(i,2,n) fac[i]=fac[i-1]*i%mod;
	inv[n]=qz(fac[n],mod-2);
	FOR(i,n-1,0) inv[i]=inv[i+1]*(i+1)%mod;
}
int C(int x,int y){
	return (fac[x]*inv[y]%mod)*inv[x-y]%mod;
}
int rev[N];
void ntt(vector<int> &a,int sign,int tot){
	int i,j,mid;
	For(i,0,tot-1) if(i<rev[i]) swap(a[i],a[rev[i]]);
	for(mid=1;mid<tot;mid<<=1){
		auto g1=qz(G,(mod-1)/(mid<<1));
		if(sign==-1) g1=qz(inv_G,(mod-1)/(mid<<1));
		for(i=0;i<tot;i+=(mid<<1)){
			auto gk=1; 
			for(j=0;j<mid;j++,gk=gk*g1%mod){
				auto x=a[i+j],y=gk*a[i+j+mid]%mod;
				a[i+j]=(x+y)%mod,a[i+j+mid]=(x-y+mod)%mod;
			}
		}
	}
	int inv=qz(tot,mod-2);
	if(sign==-1) For(i,0,tot-1) a[i]=a[i]*inv%mod;
}
vector<int> solve(int l,int r){
	int i,mid=l+r>>1;
	if(l==r){
		vector<int> t(a[l]+1);
		t[0]=((qz(2,b[l])-1)%mod+mod)%mod;
		For(i,1,a[l]) t[i]=C(a[l],i);
		return t;
	}
	auto L=solve(l,mid);
	auto R=solve(mid+1,r);
	int tot,bit=0,lenL=L.size(),lenR=R.size();
	while((1<<bit)<=lenL+lenR) bit++;
	tot=1<<bit;
	L.resize(tot);
	R.resize(tot);
	For(i,0,tot-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
	ntt(L,1,tot),ntt(R,1,tot);
	For(i,0,tot-1) L[i]=L[i]*R[i]%mod;
	ntt(L,-1,tot);
	L.resize(lenL+lenR-1);
	return L;
}
signed main(){
	int n,i,tot=0;
	init(2e5);
	cin>>n;
	For(i,1,n) cin>>a[i];
	For(i,1,n) cin>>b[i];
	auto ans=solve(1,n);
	For(i,1,n) tot+=a[i];
	For(i,0,tot) cout<<ans[i]<<' ';
	return 0;
}

上一题