General
 
 
# Author Problem Lang Verdict Time Memory Sent Judged  
196227451 Practice:
jackylova_fan_fan_fan
1794D - 29 C++17 (GCC 9-64) Wrong answer on test 9 109 ms 200924 KB 2023-03-06 11:35:51 2023-03-06 11:35:51
→ Source
// Author:dd
//(double)clock() / CLOCKS_PER_SEC <= 0.95
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define _CRT_SECURE_NO_WARNINGS
#define pb push_back
#define pii pair<int,int>
#define pll pair<long long,long long>
#define pil pair<int,long long>
#define fer(i,a,n) for(int i=(a);i<=(n);++i)
#define rep(i,n,a) for(int i=(n);i>=(a);--i)
#define ferl(i,a,n) for(long long i=(a);i<=(n);++i)
#define repl(i,n,a) for(long long i=(n);i>=(a);--i)
#define fi first
#define se second
#define elif else if
#define no cout<<"NO\n";
#define yes cout<<"YES\n";
#define none cout<<"-1\n";
#define mul_t int _t;cin>>_t;while(_t--)
#define FASTIO ios::sync_with_stdio(false);cin.tie(0);
#define Hash gp_hash_table
#define all(x) x.begin()+1,x.end()
template<class T>
void print(const T& t) {
	cout << t;
}
template<class T, class...args>
void print(const T& t, const args&...rest) {
	cout << t << ' ';
	print(rest...);
}
typedef long long ll;
typedef tree<int,null_type,less_equal<int>,rb_tree_tag,tree_order_statistics_node_update> ordered_int_set;
typedef tree<long long,null_type,less_equal<long long>,rb_tree_tag,tree_order_statistics_node_update> ordered_ll_set;
const int int_inf= 0x3f3f3f3f;
const ll ll_inf=1e16;
ll qpow(ll a,ll k,ll mod){ll res=1;a%=mod;while(k){if(k&1)res=res*a%mod;a=a*a%mod;k>>=1;}return res;}
template<class T1,class T2>
void mul(T1&x,T2 y,ll mod){x=(x+mod)%mod,y=(y+mod)%mod,x=(x*y)%mod;}
template<class T1,class T2>
void dif(T1&x,T2 y,ll mod){x=(x+mod)%mod,y=qpow(y,mod-2,mod),x=(x*y)%mod;}
template<class T1,class T2>
void add(T1&x,T2 y,ll mod){x=(x+mod)%mod,y=(y+mod)%mod,x=(x+y)%mod;}
template<class T1,class T2>
void dec(T1&x,T2 y,ll mod){x=(x+mod)%mod,y=(y+mod)%mod,x=(x-y+mod)%mod;}
template<class T>
T gcd(T a,T b){return b?gcd(b,a%b):a;}
//exgcd ax+by=gcd(a,b) ax+by=z (z > a*b-a-b)
template<class T>
T exgcd(T a,T b,T &x,T &y){T d=a;if(b==0)x=1,y=0;else{d=exgcd(b,a%b,y,x),y-=a/b*x;}return d;}
vector<bool>isnotprime;
vector<int>primes;
void getprime(int n){isnotprime.resize(n+1,0);isnotprime[1]=1;for(int i=2;i<=n;i++){if(isnotprime[i]==0)primes.push_back(i);for(size_t j=0;j<primes.size()&&i*primes[j]<=n;j++){isnotprime[i*primes[j]]=1;if(i%primes[j]==0)break;}}}
//求欧拉函数 ∑(d|n)φ(d)=n
vector<ll>phi;
void getphi(int n){isnotprime.resize(n+1,0);phi.resize(n+1,0);phi[1]=1,isnotprime[1]=1;for(int i=2;i<=n;i++){if(isnotprime[i]==0){primes.push_back(i);phi[i]=i-1;}for(size_t j=0;j<primes.size()&&i*primes[j]<=n;j++){isnotprime[i*primes[j]]=1;if(i%primes[j]==0){phi[i*primes[j]]=phi[i]*primes[j];break;}phi[i*primes[j]]=phi[i]*(primes[j]-1);}}}
struct combination{combination(int n,ll mo){siz=n,mod=mo;inv.resize(n+1,1),preinv.resize(n+1,1),fac.resize(n+1,1);for(int i=2;i<=n;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod,preinv[i]=preinv[i-1]*inv[i]%mod;for(long long i=2;i<=n;i++)fac[i]=fac[i-1]*i%mod;}ll C(int n,int m){if(n==0&&m==0)return 1;if(n<m||m<0||n<0)return 0;return fac[n]*preinv[m]%mod*preinv[n-m]%mod;}ll A(int n,int m){if(n==0&&m==0)return 1;if(n<m||m<0||n<0)return 0;return fac[n]*preinv[n-m]%mod;}vector<ll>inv;vector<ll>preinv;vector<ll>fac;private:int siz;ll mod;};
struct dsu{vector<int>fa,siz;dsu(int n){fa.resize(n+1),siz.resize(n+1);for(int i=1;i<=n;i++)fa[i]=i,siz[i]=1;}int ffind(int x){return x==fa[x]?x:fa[x]=ffind(fa[x]);}bool uuion(int x,int y){x=ffind(x),y=ffind(y);if(x==y)return false;if(siz[x]<siz[y])swap(x,y);fa[y]=x,siz[x]+=siz[y],siz[y]=0;return true;}bool check(int x,int y){return ffind(x)==ffind(y);}void init(){for(size_t i=1;i<=fa.size()-1;i++)fa[i]=i,siz[i]=1;}int getsize(int x){return siz[x];}};
template<class T>
struct segtree{int siz;vector<T>sum,minn,maxx,a;segtree(vector<T>&v){a=v;siz=a.size()-1;sum.resize(siz*4+1),minn.resize(siz*4+1),maxx.resize(siz*4+1);build(1,1,siz);}void upchange(int k,int l,int r,int x,T y){if(l==r){sum[k]=minn[k]=maxx[k]=y;return;}int mid=(l+r)>>1;if(x<=mid)upchange(k<<1,l,mid,x,y);else upchange(k<<1|1,mid+1,r,x,y);up(k);}void upadd(int k,int l,int r,int x,T y){if(l==r){sum[k]+=y,minn[k]+=y,maxx[k]+=y;return;}int mid=(l+r)>>1;if(x<=mid)upadd(k<<1,l,mid,x,y);else upadd(k<<1|1,mid+1,r,x,y);up(k);}T qsum(int k,int l,int r,int x,int y){if(l==x&&r==y)return sum[k];int mid=(l+r)>>1;if(y<=mid)return qsum(k<<1,l,mid,x,y);else if(x>mid)return qsum(k<<1|1,mid+1,r,x,y);else return qsum(k<<1,l,mid,x,mid)+qsum(k<<1|1,mid+1,r,mid+1,y);}T qmin(int k,int l,int r,int x,int y){if(l==x&&r==y)return minn[k];int mid=(l+r)>>1;if(y<=mid)return qmin(k<<1,l,mid,x,y);else if(x>mid)return qmin(k<<1|1,mid+1,r,x,y);else return min(qmin(k<<1,l,mid,x,mid),qmin(k<<1|1,mid+1,r,mid+1,y));}T qmax(int k,int l,int r,int x,int y){if(l==x&&r==y)return maxx[k];int mid=(l+r)>>1;if(y<=mid)return qmax(k<<1,l,mid,x,y);else if(x>mid)return qmax(k<<1|1,mid+1,r,x,y);else return max(qmax(k<<1,l,mid,x,mid),qmax(k<<1|1,mid+1,r,mid+1,y));}private:void build(int k,int l,int r){if(l==r){sum[k]=minn[k]=maxx[k]=a[l];return;}int mid=(l+r)>>1;build(k<<1,l,mid),build(k<<1|1,mid+1,r);up(k);}void up(int k){sum[k]=sum[k<<1]+sum[k<<1|1],minn[k]=min(minn[k<<1],minn[k<<1|1]),maxx[k]=max(maxx[k<<1],maxx[k<<1|1]);}};
struct Bitcounter{template<class T>T reversebit(T x){int f=1;if(x<0)x=-x,f=-1;vector<int>v;while(x){v.push_back(x&1);x>>=1;}reverse(v.begin(),v.end());T now=1,ans=0;for(auto&x:v)ans+=x*now,now<<=1;return ans*f;}template<class T>T lowbit(T x){return x&-x;}template<class T>int countbit(T x){int sum=0;while(x)sum+=x&1,x>>=1;return sum;}template<class T>void setbit(int*arr,T x){int cnt=0;while(x)arr[cnt]=x&1,x>>=1,++cnt;}ll getbit(int*arr,int n=61){ll sum=0;for(int i=0;i<n;i++)sum+=arr[i],sum<<=1;sum+=arr[n];return sum;}};
template<class T>
T reverseD(T x){int f=1;if(x<0)x=-x,f=-1;vector<int>v;while(x){v.push_back(x%10);x/=10;}reverse(v.begin(),v.end());T now=1,ans=0;for(auto&x:v)ans+=x*now,now*=10;return ans*f;}
template<class T1,class T2>
ll updiv(T1 a,T2 b){if(a<0)return a/b;return a/b+(a%b!=0);}
template<class T1,class T2>
ll downdiv(T1 a,T2 b){if(a>0)return a/b;return a/b-(a%b!=0);}
void strerase(string&s,char c){string t;for(auto&ch:s){if(ch==c)continue;t+=ch;}s=t;}
template<class T1,class T2>
void cmin(T1&a,T2 b){a=min<T1>(a,b);}
template<class T1,class T2>
void cmax(T1&a,T2 b){a=max<T1>(a,b);}
//-------------------------------------------
const ll mod=998244353;
combination cb(5050,mod);
ll dp[5050][5050];
void solve()
{
	int n;
	cin>>n;
	vector<int>v(n*2+1);
	fer(i,1,n*2)cin>>v[i];
	map<int,ll>p,np;
	fer(i,1,n*2)isnotprime[v[i]]?np[v[i]]++:p[v[i]]++;
	if(p.size()<n){cout<<0;return;}
	ll k=cb.fac[n];
	for(auto [a,b]:np)
	{
		if(b==0)continue;
		mul(k,cb.inv[b],mod);
	}
	dp[0][0]=1;
	int cnt=0;
	for(auto [a,b]:p)
	{
		if(b==0)continue;
		++cnt;
		fer(i,0,cnt)
		{
			if(i)add(dp[cnt][i],dp[cnt-1][i-1]*cb.inv[b-1]%mod,mod);
			add(dp[cnt][i],dp[cnt-1][i]*cb.inv[b]%mod,mod);
		}
	}
	cout<<dp[p.size()][n]*k%mod;
}
signed main()
{
	FASTIO
#define	OJ
#ifndef OJ
	freopen(".in", "r", stdin);
	freopen(".out", "w", stdout);
#endif
	getprime(1000001);
	solve();
}
/*
  1.深呼吸,不要紧张,慢慢读题,读明白题,题目往往比你想的简单。
  2.暴力枚举:枚举什么,是否可以使用一些技巧加快枚举速度(预处理、前缀和、数据结构、数论分块)。
  3.贪心:需要排序或使用数据结构(pq)吗,这么贪心一定最优吗。
  4.二分:满足单调性吗,怎么二分,如何确定二分函数返回值是什么。
  5.位运算:按位贪心,还是与位运算本身的性质有关。
  6.数学题:和最大公因数、质因子、取模是否有关。
  7.dp:怎么设计状态,状态转移方程是什么,初态是什么,使用循环还是记搜转移。
  8.搜索:dfs 还是 bfs ,搜索的时候状态是什么,需要记忆化吗。
  9.树上问题:是树形dp、树上贪心、或者是在树上搜索。
  10.图论:依靠什么样的关系建图,是求环统计结果还是最短路。
  11.组合数学:有几种值,每种值如何被组成,容斥关系是什么。
  12.交互题:log(n)次如何二分,2*n 次如何通过 n 次求出一些值,再根据剩余次数求答案。
  13.如果以上几种都不是,多半是有一个 point 你没有注意到。
 */
?
Time: ? ms, memory: ? KB
Verdict: ?
Input
?
Participant's output
?
Jury's answer
?
Checker comment
?
Diagnostics
?
Click to see test details