topic
Thinking
It is easy to find forward to seeking instant of the explosion
Is being hard ♂ Anti
So we think the total number of programs to find the number does not comply with the scheme to the inclusion-exclusion
We assume that at least there are disjoint i segment is dancing and singing rap basketball
We consider that a start point of the i-th enumeration interval, then the total number of programs is \ (C_ {n-3i} ^ i \) kinds of programs
Why is a 3 * i do?
There are clear meaning of the questions as long as 4 consecutive individual, and as long as everyone on this list assembly of the dancing and singing rap basketball on the line, the order does not require
That is for us a range, we can not choose the last three positions again, because then we would be contrary to the definition of the selected segment enumeration of i
Here that can not be selected again, referring to the beginning of a period of dancing and singing rap basketball is not in these three locations
We exclude these locations overall position can be selected is \ (the n-4i-\) , these locations are capable of misplacing
Try to write the generating function,
For the k-th student, if elected \ (t_k \) a
\(G_k(x)=\sum_{i=0}^{t_k}\frac{1}{i!}x^i\)
Note that at this time we only selected students,
For students constitute only different for different scenarios considered,
We first be rolled up,
\(F(x)=\prod_{i=1}^{4}G_i(x)\)
And because we just elected,
We also need to be sorted, and the answer is
\((n-4*i)!F(x)\)
For the latter multiplicative, we need only \ (x ^ {n-4i } \) coefficients of terms
Therefore, the answer is \ ((n-4i) f_ {n-4i} \)
As for the inclusion-exclusion, inclusion and exclusion on by the general wording written on the line
Code
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
namespace polynomial
{
const int N=1e3+10;
const int M=N<<3;
const int mod=998244353;
const int G=3;
const int SIZE=sizeof(int);
#define poly vector<int>
#define int long long
int w[M],rev[M];
poly resize(poly f,int n)
{
f.resize(n);
return f;
}
int sub(int a,int b)
{
a-=b;
if(a<0)
return a+mod;
else
return a;
}
int add(int a,int b)
{
a+=b;
if(a>=mod)
return a-mod;
else
return a;
}
int inv(int x)
{
if(x<2)
return 1;
else
return (1ll*mod-mod/x)*inv(mod%x)%mod;
}
int qkpow(int a,int b)
{
if(b==0)
return 1;
if(b==1)
return a;
int t=qkpow(a,b/2);
t=(1ll*t*t)%mod;
if(b%2==1)
t=(1ll*t*a)%mod;
return t;
}
void ntt(int *a,int lim)
{
for(int i=0;i<lim;i++)
if(i<rev[i])
swap(a[i],a[rev[i]]);
for(int len=1;len<lim;len<<=1)
{
for(int i=0;i<lim;i+=(len<<1))
{
for(int j=0;j<len;j++)
{
int x=a[i+j];
int y=1ll*w[j+len]*a[i+j+len]%mod;
a[i+j]=add(x,y);
a[i+j+len]=sub(x,y);
}
}
}
}
void ntt_init()
{
int wn;
for(int len=1;(len<<1)<M;len<<=1)
{
wn=qkpow(G,(mod-1)/(len<<1));
w[len]=1;
for(int i=1;i<len;i++)
w[i+len]=1ll*w[i+len-1]*wn%mod;
}
}
int init(int len)
{
int lim=1;
int k=0;
while(lim<len)
{
lim<<=1;
k++;
}
for(int i=0;i<lim;i++)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
return lim;
}
poly operator * (const poly &f,const poly &g)
{
int a[M]={};
int b[M]={};
int lim=init(f.size()+g.size()-1);
int inv_len=inv(lim);
poly ret;
for(int i=0;i<f.size();i++)
a[i]=f[i];
for(int i=0;i<g.size();i++)
b[i]=g[i];
ntt(a,lim);
ntt(b,lim);
for(int i=0;i<lim;i++)
a[i]=1ll*a[i]*b[i]%mod;
reverse(a+1,a+lim);
ntt(a,lim);
for(int i=0;i<f.size()+g.size()-1;i++)
ret.push_back(1ll*a[i]*inv_len%mod);
return ret;
}
#undef int
#undef poly
};
using namespace polynomial;
int n;
int num[5];
long long fac[1005];
long long ans;
long long c[1005][1005];
long long solve_c(long long n,long long m)
{
if(c[n][m])
return c[n][m];
long long ret=1;
if(m>n/2)
m=n-m;
for(long long i=n;i>=n-m+1;i--)
ret=(ret*i%mod)*qkpow(n-i+1,mod-2)%mod;
return c[n][m]=ret;
}
void prepare()
{
fac[0]=1;
for(int i=1;i<=n;i++)
fac[i]=fac[i-1]*i%mod;
}
long long solve(int k)
{
vector<long long> a[5];
for(int i=1;i<=4;i++)
for(int j=0;j<=num[i]-k;j++)
a[i].push_back(qkpow(fac[j],mod-2));
vector<long long> g;
g=a[1]*a[2];
g=g*a[3];
g=g*a[4];
return g[n-4*k]*fac[n-4*k]%mod;
}
int main()
{
ios::sync_with_stdio(false);
ntt_init();
cin>>n;
prepare();
for(int i=1;i<=4;i++)
cin>>num[i];
sort(num+1,num+5);
for(int i=0;(i<<2)<=min(n,num[1]<<2);i++)
{
long long t=solve(i)*solve_c(n-3*i,i)%mod;
//cout<<solve(i)<<' '<<solve_c(n-3*i,i)<<'\n';
if(i%2==1)
ans-=t;
else
ans+=t;
ans=ans%mod;
}
cout<<(ans+mod)%mod;
return 0;
}