QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#209884 | #6325. Peaceful Results | kkio | RE | 94ms | 54616kb | C++17 | 9.3kb | 2023-10-10 18:47:24 | 2023-10-10 18:47:25 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
namespace ZPoly
{
using LL=long long;
constexpr int MOD=998244353,G=114514,MAXN=1<<21;
inline int qpow(LL a,LL b) { int r=1;for(;b;(b&1)?r=r*a%MOD:0,a=a*a%MOD,b>>=1);return r; }
inline int madd(int x) { return x; }
inline int mmul(int x) { return x; }
inline int msub(int x,int y) { return (x-=y)<0?x+=MOD:x; }
inline int mdiv(int x,int y) { return (LL)x*qpow(y,MOD-2)%MOD; }
template<typename ...Args>inline int madd(int x,Args ...y) { return (x+=madd(y...))>=MOD?x-=MOD:x; }
template<typename ...Args>inline int mmul(int x,Args ...y) { return (LL)x*mmul(y...)%MOD; }
class Polynomial
{
private:
static constexpr int NTT_LIM=180;
static int g[MAXN+5],c1[MAXN+5],c2[MAXN+5];
int deg;
vector<int> c;
public:
static void init()
{
for(int i=2,gn;i<=MAXN;i<<=1)
{
g[i>>1]=1,gn=qpow(G,(MOD-1)/i);
for(int j=(i>>1)+1;j<i;j++) g[j]=mmul(g[j-1],gn);
}
}
static void DIT(int *a,int len)
{
for(int i=len>>1;i;i>>=1)
for(int j=0;j<len;j+=i<<1)
for(int k=0,x,y;k<i;k++)
x=a[j+k],y=a[i+j+k],a[j+k]=madd(x,y),a[i+j+k]=mmul(g[i+k],msub(x,y));
}
static void DIF(int *a,int len)
{
for(int i=1;i<len;i<<=1)
for(int j=0;j<len;j+=i<<1)
for(int k=0,x,y;k<i;k++)
x=a[j+k],y=mmul(g[i+k],a[i+j+k]),a[j+k]=madd(x,y),a[i+j+k]=msub(x,y);
int x=qpow(len,MOD-2);
for(int i=0;i<len;i++) a[i]=mmul(a[i],x);
reverse(a+1,a+len);
}
private:
static void __polyinv(const int *a,int *b,int len)
{
if(len==1) return b[0]=qpow(a[0],MOD-2),void();
__polyinv(a,b,(len+1)>>1);
int nn=1<<(__lg((len<<1)-1)+1);
memcpy(c1,a,len<<2);
memset(b+len,0,(nn-len)<<2);
memset(c1+len,0,(nn-len)<<2);
DIT(b,nn),DIT(c1,nn);
for(int i=0;i<nn;i++) b[i]=mmul(b[i],msub(2,mmul(b[i],c1[i])));
DIF(b,nn),memset(b+len,0,(nn-len)<<2);
}
static void __polyln(const int *a,int *b,int len)
{
__polyinv(a,b,len);
for(int i=1;i<len;i++) c1[i-1]=mmul(i,a[i]);
int nn=1<<(__lg((len<<1)-1)+1);
memset(b+len,0,(nn-len)<<2);
memset(c1+len,0,(nn-len)<<2);
DIT(b,nn),DIT(c1,nn);
for(int i=0;i<nn;i++) b[i]=mmul(b[i],c1[i]);
DIF(b,nn),memset(b+len,0,(nn-len)<<2);
for(int i=len-1;i>0;i--) b[i]=mdiv(b[i-1],i);
b[0]=0;
}
static void __polyexp(const int *a,int *b,int l,int r)
{
if(l==r-1) return b[l]=(l?mdiv(b[l],l):1),void();
int len=r-l,mid=(l+r)>>1;
__polyexp(a,b,l,mid);
for(int i=0;i<len;i++) c1[i]=a[i];
memcpy(c2,b+l,(mid-l)<<2);
memset(c2+mid-l,0,(r-mid)<<2);
if(len<=NTT_LIM) for(int i=len-1;i>=0;i--)
{
c1[i]=mmul(c1[i],c2[0]);
for(int j=0;j<i;j++) c1[i]=madd(c1[i],mmul(c1[j],c2[i-j]));
}
else
{
DIT(c1,len),DIT(c2,len);
for(int i=0;i<len;i++) c1[i]=mmul(c1[i],c2[i]);
DIF(c1,len);
}
for(int i=mid;i<r;i++) b[i]=madd(b[i],c1[i-l]);
__polyexp(a,b,mid,r);
}
public:
Polynomial(): deg(1),c(1){}
Polynomial(const Polynomial &p): deg(p.deg),c(p.c){}
Polynomial(Polynomial &&p): deg(p.deg),c(move(p.c)){}
explicit Polynomial(int d): deg(d),c(d){}
explicit Polynomial(const vector<int> &v): deg(v.size()),c(v){}
explicit Polynomial(const initializer_list<int> &l): deg(l.size()),c(l){}
inline int &operator [](int i) { return c[i]; }
inline int operator [](int i)const { return c[i]; }
inline int degree()const { return deg; }
inline void resize(int d) { c.resize(deg=d); }
inline Polynomial &operator +=(const Polynomial &p)
{
if(deg<p.deg) resize(p.deg);
for(int i=0;i<deg;i++) c[i]=madd(c[i],p[i]);
return *this;
}
inline Polynomial &operator -=(const Polynomial &p)
{
if(deg<p.deg) resize(p.deg);
for(int i=0;i<deg;i++) c[i]=msub(c[i],p[i]);
return *this;
}
inline Polynomial &operator *=(const Polynomial &p)
{
int n=deg,m=p.deg;resize(n+m-1);
if(n+m<NTT_LIM)
{
memcpy(c1,c.data(),n<<2);
memset(c2,0,(n+m-1)<<2);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
c2[i+j]=madd(c2[i+j],mmul(c1[i],p[j]));
memcpy(c.data(),c2,(n+m-1)<<2);
}
else
{
int nn=1<<(__lg(n+m-1)+1);
memcpy(c1,c.data(),n<<2),memcpy(c2,p.c.data(),m<<2);
memset(c1+n,0,(nn-n)<<2),memset(c2+m,0,(nn-m)<<2);
DIT(c1,nn),DIT(c2,nn);
for(int i=0;i<nn;i++) c1[i]=mmul(c1[i],c2[i]);
DIF(c1,nn),memcpy(c.data(),c1,deg<<2);
}
return *this;
}
friend inline Polynomial derivative(const Polynomial &p)
{
Polynomial q(p.deg-1);
for(int i=1;i<p.deg;i++) q[i-1]=mmul(p[i],i);
return q;
}
friend inline Polynomial integral(const Polynomial &p)
{
Polynomial q(p.deg+1);
for(int i=1;i<p.deg;i++) q[i+1]=mdiv(p[i],i+1);
return q;
}
inline Polynomial inv()const
{
if(c[0]==0) cerr<<"[x^0]f(x)=0, f(x)^-1 doesn't exist.\n",abort();
int nn=1<<(__lg((deg<<1)-1)+1);
Polynomial q(nn);
__polyinv(c.data(),q.c.data(),deg);
return q.resize(deg),q;
}
friend inline Polynomial ln(const Polynomial &p)
{
if(p[0]!=1) cerr<<"[x^0]f(x)!=1, ln(f(x)) doesn't exist.\n",abort();
int nn=1<<(__lg((p.deg<<1)-1)+1);
Polynomial q(nn);
__polyln(p.c.data(),q.c.data(),p.deg);
return q.resize(p.deg),q;
}
friend inline Polynomial exp(const Polynomial &p)
{
if(p[0]!=0) cerr<<"[x^0]f(x)!=0, exp(f(x)) doesn't exist.\n",abort();
static int c[MAXN];
int nn=1<<(__lg(p.deg-1)+1);
for(int i=0;i<p.deg;i++) c[i]=mmul(i,p[i]);
Polynomial q(nn);
__polyexp(c,q.c.data(),0,nn);
return q.resize(p.deg),q;
}
friend inline pair<Polynomial,Polynomial> div(const Polynomial &f,const Polynomial &g)
{
if(f.deg<g.deg) return make_pair(Polynomial{0},f);
int n=f.deg-1,m=g.deg-1;
Polynomial fr(n+1),gr(m+1);
for(int i=0;i<=n;i++) fr[i]=f[n-i];
for(int i=0;i<=m;i++) gr[i]=g[m-i];
fr.resize(n-m+1),gr.resize(n-m+1),fr*=gr.inv();
fr.resize(n-m+1),reverse(fr.c.begin(),fr.c.end());
gr=f-fr*g,gr.resize(m);
return make_pair(fr,gr);
}
inline Polynomial &operator =(const Polynomial &p)
{ return deg=p.deg,c=p.c,*this; }
inline Polynomial &operator =(Polynomial &&p)
{ return deg=p.deg,c=move(p.c),*this; }
inline Polynomial &operator *=(int k)
{ for(auto &i: c) i=mmul(i,k);return *this; }
inline Polynomial &operator /=(const Polynomial &rhs)
{ return (*this)*=rhs.inv(); }
inline Polynomial &operator %=(const Polynomial &rhs)
{ return (*this)=div(*this,rhs).second; }
inline Polynomial operator +(const Polynomial &rhs)const
{ return Polynomial(*this)+=rhs; }
inline Polynomial operator -(const Polynomial &rhs)const
{ return Polynomial(*this)-=rhs; }
inline Polynomial operator *(const Polynomial &rhs)const
{ return Polynomial(*this)*=rhs; }
inline Polynomial operator /(const Polynomial &rhs)const
{ return Polynomial(*this)/=rhs; }
inline Polynomial operator %(const Polynomial &rhs)const
{ return div(*this,rhs).second; }
friend inline Polynomial operator *(const Polynomial &p,int k)
{ return Polynomial(p)*=k; }
friend inline Polynomial operator *(int k,const Polynomial &p)
{ return Polynomial(p)*=k; }
};
int Polynomial::g[]={},Polynomial::c1[]={},Polynomial::c2[]={};
}
using Poly=ZPoly::Polynomial;
const int maxn=3e6+10,mod=998244353;
int n,A[3],B[3],C[3],q;
int fac[maxn],ifac[maxn],inv[maxn];
Poly f,g;
int main()
{
Poly::init();
scanf("%d",&n);
scanf("%d%d%d",&A[1],&A[2],&A[0]);
scanf("%d%d%d",&B[1],&B[2],&B[0]);
scanf("%d%d%d",&C[1],&C[2],&C[0]);
fac[0]=ifac[0]=inv[1]=1;
for(int i=2;i<=n;i++)inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
for(int i=1;i<=n;i++)fac[i]=1ll*fac[i-1]*i%mod,ifac[i]=1ll*ifac[i-1]*inv[i]%mod;
int a[6][7]={
{1,0,1,0,1,0,A[0]-A[1]},
{0,1,0,1,0,1,A[0]-A[2]},
{1,0,0,-1,-1,1,B[0]-B[1]},
{0,1,1,-1,-1,0,B[0]-B[2]},
{1,0,-1,1,0,-1,C[0]-C[1]},
{0,1,-1,0,1,-1,C[0]-C[2]}
};
// for(int i=0;i<6;i++,putchar('\n'))
// for(int j=0;j<7;j++)
// printf("%d ",a[i][j]);
int ans=0;
for(int i=0;i<6;i++)
{
int pos=-1;
for(int j=i;j<6;j++)
if(a[j][i]!=0){pos=j;break;}
if(pos==-1){puts("0");return 0;}
swap(a[i],a[pos]);
for(int j=i+1;j<7;j++)if(a[i][j]%a[i][i]!=0){puts("0");return 0;}else a[i][j]/=a[i][i];
a[i][i]=1;
for(int j=0;j<6;j++)
if(j!=i)
{
int mul=a[j][i];
for(int k=i;k<7;k++)
a[j][k]-=mul*a[i][k];
}
}
// for(int i=0;i<6;i++,putchar('\n'))
// for(int j=0;j<7;j++)
// printf("%d ",a[i][j]);
int zsum=n+a[0][6]+a[1][6]+a[2][6]+a[3][6]+a[4][6]+a[5][6];
//printf("%d\n",zsum);
if(zsum<0||zsum%3){puts("0");return 0;}
zsum/=3;
f.resize(zsum+1);
g.resize(zsum+1);
for(int i=max({0,a[0][6],a[1][6]});i<=zsum;i++)
f[i]=1ll*ifac[i]*ifac[i-a[0][6]]%mod*ifac[i-a[1][6]]%mod;
for(int i=max({0,a[2][6],a[3][6]});i<=zsum;i++)
g[i]=1ll*ifac[i]*ifac[i-a[2][6]]%mod*ifac[i-a[3][6]]%mod;
//for(int i=0;i<n;i++)printf("%d ",f[i]);putchar('\n');
//for(int i=0;i<n;i++)printf("%d ",g[i]);putchar('\n');
f*=g;
//for(int i=0;i<n;i++)printf("%d ",f[i]);putchar('\n');
//printf("%d\n",min({zsum,C[0],C[1]-a[4][6],C[2]-a[5][6]}));
for(int i=max({0,a[4][6],a[5][6]});i<=zsum;i++)
ans=(ans+1ll*f[zsum-i]*ifac[i]%mod*ifac[i-a[4][6]]%mod*ifac[i-a[5][6]]%mod)%mod;
ans=1ll*ans*fac[n]%mod;
printf("%d\n",ans);
}
/*
15
1 6 8
2 6 7
7 3 5
*/
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 12ms
memory: 20584kb
input:
2 2 0 0 1 1 0 1 0 1
output:
2
result:
ok 1 number(s): "2"
Test #2:
score: 0
Accepted
time: 11ms
memory: 19560kb
input:
3 0 1 2 3 0 0 1 1 1
output:
0
result:
ok 1 number(s): "0"
Test #3:
score: 0
Accepted
time: 30ms
memory: 25632kb
input:
333333 111111 111111 111111 111111 111111 111111 111111 111111 111111
output:
383902959
result:
ok 1 number(s): "383902959"
Test #4:
score: 0
Accepted
time: 88ms
memory: 54616kb
input:
1500000 500000 500000 500000 500000 500000 500000 500000 500000 500000
output:
355543262
result:
ok 1 number(s): "355543262"
Test #5:
score: 0
Accepted
time: 94ms
memory: 52612kb
input:
1499999 499999 499999 500001 499999 499999 500001 499999 499999 500001
output:
934301164
result:
ok 1 number(s): "934301164"
Test #6:
score: -100
Runtime Error
input:
1500000 1 0 1499999 1499999 1 0 0 1499999 1