QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#115268 | #6323. Range NEQ | xaphoenix# | AC ✓ | 466ms | 101016kb | C++14 | 24.8kb | 2023-06-25 13:59:22 | 2023-06-25 13:59:24 |
Judging History
answer
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pf push_front
#define LC k<<1
#define RC k<<1|1
#define IO cin.sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define all(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())
#define rep(i,a,n) for (int i = a; i < n; i++)
#define repn(i,a,n) for (int i = a; i <= n; i++)
#define per(i,a,n) for (int i = (n) - 1; i >= a; i--)
#define pern(i,a,n) for (int i = n; i >= a; i--)
typedef long long LL;
typedef long double LD;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<int, LL> PIL;
typedef pair<LL, int> PLI;
typedef pair<double, double> PDD;
typedef pair<ull, ull> PUU;
typedef pair<LL, LL> PLL;
const int N = 1100000;
const int M = 1100000;
const int mod = 998244353;
const int inf = (int)1e9;
const LL INF = 1e18;
const double eps = 1e-9;
mt19937_64 Rand((unsigned long long)new char);
#define rand Rand
#define NTT
#define MOD
#define polyn Poly::poly<int>
namespace Poly {
/*
step 0. select proper BASE & mod (#define MOD)
step 1. select proper fft (#define FFT/NTT/FWT/MTT)
step 2. select proper atomic operator (w/o mod, automatically)
step 3. select proper multiplication (FFT/NTT/MTT,cyclic FTT)
*/
// common definition & function
const int BASE = 22;
const int MAXN = 1 << BASE;
const int BRUTEL = 128;
#ifdef MTT
const int mod = 1000000007;
#else
const int mod = 998244353;
#endif
int pow_mod(int a, LL e) {
int res = 1;
for (; e; a = (LL)a * a % mod, e >>= 1) if (e & 1) res = (LL)res * a % mod;
return res;
}
int pow_mod(int a, LL e, int mod) {
int res = 1;
for (; e; a = (LL)a * a % mod, e >>= 1) if (e & 1) res = (LL)res * a % mod;
return res;
}
int modsqr(int a, int n) {
int b, k, i, x;
if (n == 2) return a % n;
if (pow_mod(a, (n - 1) / 2, n) == 1) {
if (n % 4 == 3) x = pow_mod(a, (n + 1) / 4, n);
else {
for (b = 1; pow_mod(b, (n - 1) / 2, n) == 1; b++);
i = (n - 1) / 2;
k = 0;
do {
i /= 2;
k /= 2;
if ((pow_mod(a, i, n) * (LL)pow_mod(b, k, n) + 1) % n == 0) k += (n - 1) / 2;
} while (i % 2 == 0);
x = (pow_mod(a, (i + 1) / 2, n) * (LL)pow_mod(b, k / 2,n )) % n;
}
if (x * 2 > n) x = n - x;
return x;
}
return -1;
}
// select proper fft
#if defined(FFT) || defined(MTT)
const double PI = acos(-1.0);
struct complex {
double r, i;
complex(double _r = 0.0, double _i = 0.0) {r = _r; i =_i;}
complex operator + (const complex &b){return complex(r + b.r, i + b.i);}
complex operator - (const complex &b){return complex(r - b.r, i - b.i);}
complex operator * (const complex &b){return complex(r * b.r - i * b.i, r * b.i + i * b.r);}
complex conj() {return complex(r, -i);}
};
complex W[2][MAXN*2];
void init() {
for (int h = 2; h <= MAXN; h <<= 1)
for (int d = 0; d < h / 2; d++) {
W[0][h + d] = complex(cos(2 * d * PI / h), sin(2 * d * PI / h));
W[1][h + d] = complex(cos(-2 * d * PI / h), sin(-2 * d * PI / h));
}
}
void change(complex y[], int len) {
int i, j, k;
for(i = 1, j = len / 2; i < len - 1; i++) {
if (i < j) swap(y[i], y[j]);
k = len / 2;
while (j >= k) {
j -= k;
k /= 2;
}
if (j < k) j += k;
}
}
void fft(complex y[],int len,int type)
{
change(y,len);
for(int h=2;h<=len;h<<=1)
for(int j=0;j<len;j+=h)
for(int k=j,d=0;k<j+h/2;k++,d++)
{
complex w;
if (type==1) w=W[0][h+d];
else w=W[1][h+d];
complex u=y[k],t=w*y[k+h/2];
y[k]=u+t;
y[k+h/2]=u-t;
}
if(type==-1) for(int i=0;i<len;i++) y[i].r/=len;
}
#endif
#ifdef NTT
const int g=3;
int W[2][MAXN*2];
void init()
{
for (int h=2;h<=MAXN;h<<=1)
{
LL x=pow_mod(g,(mod-1)/h);
LL y=pow_mod(x,mod-2);
W[0][h]=W[1][h]=1;
for (int d=1;d<h/2;d++)
W[0][h+d]=(LL)x*W[0][h+d-1]%mod,W[1][h+d]=(LL)y*W[1][h+d-1]%mod;
}
}
void change(int y[],int len)
{
int i,j,k;
for(i=1,j=len/2;i<len-1;i++)
{
if (i<j) swap(y[i],y[j]);
k=len/2;
while(j>=k)
{
j-=k;
k/=2;
}
if(j<k) j+=k;
}
}
void fft(int y[],int len,int type)
{
change(y,len);
for(int h=2;h<=len;h<<=1)
for(int j=0;j<len;j+=h)
for(int k=j,d=0;k<j+h/2;k++,d++)
{
int w;
if (type==1) w=W[0][h+d];
else w=W[1][h+d];
int u=y[k],t=(LL)w*y[k+h/2]%mod;
y[k]=(u+t)%mod;
y[k+h/2]=(u-t+mod)%mod;
}
if(type==-1) for(int i=0,x=pow_mod(len,mod-2);i<len;i++) y[i]=(LL)y[i]*x%mod;
}
#endif
#ifdef FWT
int set_size[MAXN];
void init()
{
for (int i=0;i<MAXN;i++)
set_size[i]=__builtin_popcount(i);
}
void fwt_xor(int *a, int length, int type) {
int len=-1;
for (int x = length; x; ++len, x >>= 1);
repn(i, 1, len) for (int j = 0; j < length; j += 1 << i)
for (int k = j, szk = 1 << i - 1; k < j + szk; ++k) {
int s = a[k], t = a[k + szk];
a[k] = s + t >= mod ? s + t - mod : s + t;
a[k + szk] = s - t < 0 ? s - t + mod : s - t;
}
if (type == 1) return;
int inv = pow_mod(length, mod - 2);
rep(i, 0, length) a[i] = 1LL * a[i] * inv % mod;
}
void fwt_and(int *a,int length,int type)
{
int len=-1;
for (int x=length;x;++len,x>>=1);
for (int i=1;i<=len;++i)
for (int j=0;j<length;j+=1<<i)
for (int k=j,szk=1<<i-1;k<j+szk;++k)
a[k]=(a[k]+1LL*type*a[k+szk]+mod)%mod;
}
void fwt_or(int *a,int length,int type)
{
int len=-1;
for (int x=length;x;++len,x>>=1);
for (int i=1;i<=len;++i)
for (int j=0;j<length;j+=1<<i)
for (int k=j,szk=1<<i-1;k<j+szk;++k)
a[k+szk]=(a[k+szk]+1LL*type*a[k]+mod)%mod;
}
#endif
template<class T>
struct poly
{
T *a;
int length,size;
void clear()
{
delete [] a;
a=nullptr;
size=length=0;
}
void apply(int size)
{
if (!size) return;
a=new T [size]();
this->size=size;
}
void resize(int size)
{
if (!size) return;
T *aux=a;
a=new T [size]();
memcpy(a,aux,sizeof(T)*(length+1));
if (this->size) delete [] aux;
this->size=size;
}
void initpoly(const poly &p,int length)
{
clear();
apply(length+1);
memcpy(a,p.a,sizeof(T)*(std::min(length,p.length)+1));
this->length=length;
}
void print()
{
for (int i=0;i<=length;i++)
{
printf("%d",a[i]);
if (i!=length) printf(" ");
else printf("\n");
}
}
void setlength(int length)
{
if (length>=size) resize(length+1);
if (length>=this->length) { this->length=length; return;}
memset(a+length+1,0,sizeof(T)*(this->length - length));
this->length=length;
}
void reverse()
{
std::reverse(a,a+length+1);
}
poly():a(nullptr),length(-1),size(0) {}
poly(int length):a(nullptr),length(length) {apply(length+1);}
poly(const poly&p):a(nullptr) {initpoly(p,p.length);}
poly(const poly&p,int length):a(nullptr) {initpoly(p,length);}
poly(T p[],int n) {
apply(n+2<<1);
length=n;
memcpy(a,p,sizeof(T)*(n+1));
}
~poly() {clear();}
// select proper atomic function below
#ifndef MOD
inline T add(const T &a,const T &b) const {return a+b;}
inline T sub(const T &a,const T &b) const {return a-b;}
inline T mul(const T &a,const T &b) const {return a*b;}
inline T mod_inv(const T &a) const { return 1.0/a;}
#else
inline T add(const T &a,const T &b) const {return (a+b)%mod;}
inline T sub(const T &a,const T &b) const {return (a-b+mod)%mod;}
inline T mul(const T &a,const T &b) const {return (LL)a*b%mod;}
inline T mod_inv(const T &a) const {return pow_mod(a,mod-2);}
#endif
T value(T x)
{
T res=0,now=1;
for (int i=0;i<=length;i++)
{
res=add(res,mul(a[i],now));
now=mul(now,x);
}
return res;
}
T &operator [](int pos) {return a[pos];}
poly &operator = (const poly &p)
{
if (&p!=this) initpoly(p,p.length);
return *this;
}
poly operator << (const int &dis) const {
poly res(length+dis);
memcpy(res.a+dis,a,sizeof(T)*(length+1));
return res;
}
poly operator >> (const int &dis) const {
if (dis>length) return poly(-1);
poly res(length-dis);
memcpy(res.a,a+dis,sizeof(T)*(res.length+1));
return res;
}
poly operator + (const poly &p) const {
if (length==-1) return p;
if (p.length==-1) return *this;
poly res(*this,std::max(length,p.length));
for (int i=0;i<=p.length;i++)
res.a[i]=add(res.a[i],p.a[i]);
return res;
}
poly operator - (const poly &p) const {
if (length==-1) return p;
if (p.length==-1) return *this;
poly res(*this,std::max(length,p.length));
for (int i=0;i<=p.length;i++)
res.a[i]=sub(res.a[i],p.a[i]);
return res;
}
poly operator - () const {
poly res(length);
for (int i=0;i<=length;i++)
res[i]=sub(0,a[i]);
return res;
}
poly operator * (const T &p) const {
poly res(length);
for (int i=0;i<=length;i++)
res[i]=mul(a[i],p);
return res;
}
poly operator + (const T &p) const {
poly res(length);
for (int i=0;i<=length;i++)
res[i]=add(a[i],p);
return res;
}
poly operator - (const T &p) const {
poly res(length);
for (int i=0;i<=length;i++)
res[i]=sub(a[i],p);
return res;
}
// brute force for small poly
void mul(T *a,T *b,T *c,int lengtha,int lengthb,int lengthret,int n) const {
for (int i=0;i<=n;i++)
c[i]=0;
for (int i=0;i<=lengtha;i++)
for (int j=0;j<=std::min(lengthb,n-i);j++)
c[i+j]=add(c[i+j],mul(a[i],b[j]));
}
// select proper multiplication
#ifdef FFT
void conv(T *a,T *b,T *c,int lengtha,int lengthb,int lengthret,int n) const
{
if (n<BRUTEL)
{
mul(a,b,c,lengtha,lengthb,lengthret,n);
return;
}
complex *a1=new complex [lengthret];
complex *a2=new complex [lengthret];
for (int i=0;i<lengthret;i++)
{
a1[i]=i>lengtha?0:a[i];
a2[i]=i>lengthb?0:b[i];
}
fft(a1,lengthret,1);
fft(a2,lengthret,1);
for (int i=0;i<lengthret;i++)
a1[i]=a1[i]*a2[i];
fft(a1,lengthret,-1);
for (int i=0;i<=n;i++)
c[i]=(a1[i].r+0.5);
delete [] a1;
delete [] a2;
}
poly operator * (const poly &p) const {
if (length==-1||p.length==-1) return poly(-1);
int n=length+p.length;
int lengthret=1;
for (;lengthret<=n;lengthret<<=1);
poly res(n);
conv(a,p.a,res.a,length,p.length,lengthret,n);
return res;
}
#endif
#ifdef MTT
void merge_fft(complex *a,complex *b,int lengthret,int type) const
{
for (int i=0;i<lengthret;i++)
a[i]=a[i]+complex(0,1.0)*b[i];
fft(a,lengthret,type);
b[0]=a[0].conj();
for (int i=1;i<lengthret;i++)
b[i]=a[lengthret-i].conj();
for (int i=0;i<lengthret;i++)
{
complex cur_c=a[i],cur_d=b[i];
a[i]=(cur_c+cur_d)*complex(0.5,0);
b[i]=(cur_c-cur_d)*complex(0,-0.5);
}
}
void conv(T *a,T *b,T *c,int lengtha,int lengthb,int lengthret,int n) const
{
if (n<BRUTEL)
{
mul(a,b,c,lengtha,lengthb,lengthret,n);
return;
}
complex *ka=new complex [lengthret];
complex *kb=new complex [lengthret];
complex *ra=new complex [lengthret];
complex *rb=new complex [lengthret];
const int s=1<<15;
for (int i=0;i<lengthret;i++)
{
ka[i]=i>lengtha?0:a[i]/s;
ra[i]=i>lengtha?0:a[i]%s;
kb[i]=i>lengthb?0:b[i]/s;
rb[i]=i>lengthb?0:b[i]%s;
}
merge_fft(ka,ra,lengthret,1);
merge_fft(kb,rb,lengthret,1);
// ka -> t1, kb -> t2, ra -> t3 for save memory;
for (int i=0;i<lengthret;i++)
{
complex cur_ka=ka[i],cur_kb=kb[i];
complex cur_ra=ra[i],cur_rb=rb[i];
ka[i]=cur_ka*cur_kb;
kb[i]=cur_ka*cur_rb+cur_ra*cur_kb;
ra[i]=cur_ra*cur_rb;
}
fft(ka,lengthret,-1);
fft(kb,lengthret,-1);
fft(ra,lengthret,-1);
for (int i=0;i<=n;i++)
c[i]=((LL)(ka[i].r+0.5)%mod*(LL)s*s+(LL)(kb[i].r+0.5)%mod*(LL)s+(LL)(ra[i].r+0.5))%mod;
delete [] ka;
delete [] ra;
delete [] kb;
delete [] rb;
}
poly operator * (const poly &p) const {
if (length==-1||p.length==-1) return poly(-1);
int n=length+p.length;
int lengthret=1;
for (;lengthret<=n;lengthret<<=1);
poly res(n);
conv(a,p.a,res.a,length,p.length,lengthret,n);
return res;
}
#endif
#ifdef NTT
void conv(T *a,T *b,T *c,int lengtha,int lengthb,int lengthret,int n) const
{
if (n<BRUTEL)
{
mul(a,b,c,lengtha,lengthb,lengthret,n);
return;
}
int *a1=new int [lengthret];
int *a2=new int [lengthret];
for (int i=0;i<lengthret;i++)
{
a1[i]=i>lengtha?0:a[i];
a2[i]=i>lengthb?0:b[i];
}
fft(a1,lengthret,1);
fft(a2,lengthret,1);
for (int i=0;i<lengthret;i++)
a1[i]=(LL)a1[i]*a2[i]%mod;
fft(a1,lengthret,-1);
for (int i=0;i<=n;i++)
c[i]=a1[i];
delete [] a1;
delete [] a2;
}
poly operator * (const poly &p) const {
if (length==-1||p.length==-1) return poly(-1);
int n=length+p.length;
int lengthret=1;
for (;lengthret<=n;lengthret<<=1);
poly res(n);
conv(a,p.a,res.a,length,p.length,lengthret,n);
return res;
}
#endif
#if defined(NTT) || defined(MTT)
// c^0, c^1, ..., c^m
poly czt(T c,int m)
{
int n=m+length;
int lengthret=1;
for (;lengthret<=n;lengthret<<=1);
T *a1 = new T [lengthret];
T *a2 = new T [lengthret];
T *a3 = new T [lengthret];
T *w[3];
w[0] = new T [lengthret];
w[1] = new T [lengthret];
w[2] = new T [lengthret];
w[0][0]=1,w[0][1]=c,w[1][0]=w[1][1]=w[2][0]=w[2][1]=1;
for (int i=2;i<lengthret;i++)
{
w[0][i]=mul(w[0][i-1],c);
w[1][i]=mul(w[0][i-1],w[1][i-1]);
w[2][i]=mod_inv(w[1][i]);
}
for (int i=0;i<lengthret;i++)
{
a1[i]=w[1][i];
a2[i]=i>length?0:mul(w[2][i],a[i]);
}
delete [] w[0];
delete [] w[1];
reverse(a1,a1+lengthret);
poly res(m);
conv(a1,a2,a3,lengthret-1,lengthret-1,lengthret,lengthret-1);
for (int i=0;i<=m;i++)
res[i]=mul(a3[lengthret-1-i],w[2][i]);
delete [] a1;
delete [] a2;
delete [] a3;
delete [] w[2];
return res;
}
#endif
#ifdef FWT
poly operator ^ (const poly &p) const {
int n=std::max(length,p.length);
int lengthret=1;
for (;lengthret<=n;lengthret<<=1);
int *a1=new int [lengthret];
int *a2=new int [lengthret];
for (int i=0;i<lengthret;i++)
{
a1[i]=i>length?0:a[i];
a2[i]=i>p.length?0:p.a[i];
}
fwt_xor(a1,lengthret,1);
fwt_xor(a2,lengthret,1);
for (int i=0;i<lengthret;i++)
a1[i]=(LL)a1[i]*a2[i]%mod;
fwt_xor(a1,lengthret,-1);
poly res(n);
for (int i=0;i<=n;i++)
res[i]=a1[i];
delete [] a1;
delete [] a2;
return res;
}
poly operator | (const poly &p) const {
int n=std::max(length,p.length);
int lengthret=1;
for (;lengthret<=n;lengthret<<=1);
int *a1=new int [lengthret];
int *a2=new int [lengthret];
for (int i=0;i<lengthret;i++)
{
a1[i]=i>length?0:a[i];
a2[i]=i>p.length?0:p.a[i];
}
fwt_or(a1,lengthret,1);
fwt_or(a2,lengthret,1);
for (int i=0;i<lengthret;i++)
a1[i]=(LL)a1[i]*a2[i]%mod;
fwt_or(a1,lengthret,-1);
poly res(n);
for (int i=0;i<=n;i++)
res[i]=a1[i];
delete [] a1;
delete [] a2;
return res;
}
poly operator & (const poly &p) const {
int n=std::max(length,p.length);
int lengthret=1;
for (;lengthret<=n;lengthret<<=1);
int *a1=new int [lengthret];
int *a2=new int [lengthret];
for (int i=0;i<lengthret;i++)
{
a1[i]=i>length?0:a[i];
a2[i]=i>p.length?0:p.a[i];
}
fwt_and(a1,lengthret,1);
fwt_and(a2,lengthret,1);
for (int i=0;i<lengthret;i++)
a1[i]=(LL)a1[i]*a2[i]%mod;
fwt_and(a1,lengthret,-1);
poly res(n);
for (int i=0;i<=n;i++)
res[i]=a1[i];
delete [] a1;
delete [] a2;
return res;
}
poly operator * (const poly &p) const {
int n=std::max(length,p.length);
int lengthret=1;
for (;lengthret<=n;lengthret<<=1);
int *a1[BASE],*a2[BASE],*a3[BASE];
for (int i=0;i<BASE;i++)
{
a1[i]=new int [lengthret];
a2[i]=new int [lengthret];
a3[i]=new int [lengthret];
for (int j=0;j<lengthret;j++)
{
a1[i][j]=(j>length||set_size[j]!=i)?0:a[j];
a2[i][j]=(j>p.length||set_size[j]!=i)?0:p.a[j];
a3[i][j]=0;
}
fwt_or(a1[i],lengthret,1);
fwt_or(a2[i],lengthret,1);
}
for (int i=0;i<BASE;i++)
for (int j=0;j<BASE-i;j++)
for (int k=0;k<lengthret;k++)
a3[i+j][k]=(a3[i+j][k]+(LL)a1[i][k]*a2[j][k])%mod;
for (int i=0;i<BASE;i++)
fwt_or(a3[i],lengthret,-1);
poly res(n);
for (int i=0;i<=n;i++)
res[i]=a3[set_size[i]][i];
for (int i=0;i<BASE;i++)
{
delete [] a1[i];
delete [] a2[i];
delete [] a3[i];
}
return res;
}
#endif
friend poly operator - (const T &q,const poly &p) {return p-q;}
friend poly operator + (const T &q,const poly &p) {return p+q;}
friend poly operator * (const T &q,const poly &p) {return p*q;}
poly &operator += (const poly &p){*this=*this+p; return *this;}
poly &operator -= (const poly &p){*this=*this-p; return *this;}
poly &operator *= (const poly &p){*this=*this*p; return *this;}
poly &operator *= (const T &p){*this=*this*p; return *this;}
poly der() const
{
if (length==-1) return poly(-1);
poly res(length-1);
for (int i=0;i<length;i++)
res[i]=mul(a[i+1],i+1);
return res;
}
poly integral() const
{
int *a1 = new int [length+3];
a1[0]=0,a1[1]=1;
for (int i=2;i<=length+1;i++)
a1[i]=sub(0,mul(mod/i,a1[mod%i]));
poly res(length+1);
for (int i=length+1;i;i--)
res[i]=mul(a[i-1],a1[i]);
delete [] a1;
return res;
}
poly inv(int n) const
{
poly res(1);
res[0]=pow_mod(a[0],mod-2);
int len=1;
while (len<n) len*=2;
for (int degree=0;degree<len;)
{
degree=degree<<1|1;
poly a1(*this,degree),a2(res);
res*=res,res.setlength(degree);
a1*=res,a1.setlength(degree);
res=2*a2-a1;
}
res.setlength(n-1);
return res;
}
poly operator / (const poly &p) const
{
if (p.length>length) return poly(-1);
poly a(*this),b(p);
a.reverse(),a.setlength(length-p.length+1);
b.reverse(),b.setlength(length-p.length+1);
poly res(b.inv(length-p.length+1));
res*=a;
res.setlength(length-p.length);
res.reverse();
return res;
}
poly operator % (const poly &p) const
{
poly res=(*this)-(*this)/p*p;
res.setlength(p.length-1);
return res;
}
poly &operator /= (const poly &p) {*this=*this/p; return *this;}
poly &operator %= (const poly &p) {*this=*this%p; return *this;}
// a[0]=1 must
poly ln(int n) const
{
poly res=(*this).der()*(*this).inv(n);
res.setlength(n);
res=res.integral();
res.setlength(n-1);
return res;
}
poly sqrt(int n) const
{
poly res(1);
res[0]=modsqr(a[0],mod);
for (int degree=0;degree<n;)
{
degree=degree<<1|1;
poly a1(*this,degree),a2(res);
res=res*res+a1,res.setlength(degree);
a2=(a2*2).inv(degree+1);
res=res*a2;
res.setlength(degree);
}
res.setlength(n-1);
return res;
}
// a[0]=0;
poly exp(int n) const
{
poly res(1);
res[0]=1;
poly unit(res);
for (int degree=0;degree<n;)
{
degree=degree<<1|1;
poly a1(*this,degree),a2(res);
a1=unit-a2.ln(degree+1)+a1;
a1.setlength(degree);
res=a1*a2;
res.setlength(degree);
}
res.setlength(n-1);
return res;
}
// k1 = K % mod, k2 = K % mod-1, k3 = min(n, K)
poly pow(int n,T k1,T k2=-1, T k3=-1) const
{
if (k2==-1) k2=k1;
if (k3==-1) k3=k1;
int pos=-1;
for (int i=0;i<=length;i++)
if (a[i]!=0)
{
pos=i;
break;
}
// sqrt(0)
if (pos==-1) return (*this);
poly res=(*this)>>pos;
T coef=res[0],inverse=mod_inv(res[0]);
res=res*inverse;
res=res.ln(n);
res=res*k1;
res=res.exp(n);
pos=min((LL)pos*(LL)k3,(LL)n);
res=(res*pow_mod(coef,k2))<<pos;
res.setlength(n-1);
return res;
}
poly sin(int n) const
{
static T i=modsqr(mod-1,mod);
poly a1=((*this)*i).exp(n);
poly a2=((*this)*sub(0,i)).exp(n);
poly res=a1-a2;
res=res*mod_inv(mul(2,i));
return res;
}
poly cos(int n) const
{
static T i=modsqr(mod-1,mod);
poly a1=((*this)*i).exp(n);
poly a2=((*this)*sub(0,i)).exp(n);
poly res=a1+a2;
res=res*mod_inv(2);
return res;
}
// a[0]=0
poly arcsin(int n) const
{
poly res(1);
res[0]=1;
poly unit(res);
poly a1=(*this).der();
poly a2=(*this)*(*this);
a2.setlength(n-1);
a2=unit-a2;
a2=a2.sqrt(n);
a1=a1*a2.inv(n);
a1.setlength(n-1);
res=a1.integral();
res.setlength(n-1);
return res;
}
// a[0]=0
poly arccos(int n) const
{
poly res(1);
res[0]=1;
poly unit(res);
poly a1=(*this).der();
poly a2=(*this)*(*this);
a2.setlength(n-1);
a2=unit-a2;
a2=a2.sqrt(n);
a1=-a1*a2.inv(n);
a1.setlength(n-1);
res=a1.integral();
res.setlength(n-1);
return res;
}
// a[0]=0
poly arctan(int n) const
{
poly res(1);
res[0]=1;
poly unit(res);
poly a1=(*this).der();
poly a2=(*this)*(*this);
a2.setlength(n-1);
a2=unit+a2;
a1=a1*a2.inv(n);
a1.setlength(n-1);
res=a1.integral();
res.setlength(n-1);
return res;
}
void multi_eval(T b[],int m)
{
int M=4*m;
poly *moder = new poly [M];
poly *rem = new poly [M];
int *l = new int [M];
int *r = new int [M];
memset(l,0,sizeof(int)*(M));
memset(r,0,sizeof(int)*(M));
l[1]=1,r[1]=m;
for (int i=1;i<M;i++)
{
if (l[i]==r[i]) continue;
int mid=(l[i]+r[i])/2;
l[i<<1]=l[i],r[i<<1]=mid;
l[i<<1|1]=mid+1,r[i<<1|1]=r[i];
}
for (int i=M-1;i;i--)
{
if (l[i]==r[i])
{
if (l[i])
{
moder[i]=poly(1),moder[i][0]=sub(0,b[l[i]]),moder[i][1]=1;
}
continue;
}
moder[i]=moder[i<<1]*moder[i<<1|1];
moder[i].setlength(r[i]-l[i]+1);
}
rem[1]=(*this)%moder[1];
for (int i=1;i<M;i++)
{
if (l[i]==r[i]) continue;
rem[i<<1]=rem[i]%moder[i<<1];
rem[i<<1|1]=rem[i]%moder[i<<1|1];
}
for (int i=1;i<M;i++)
if (l[i]&&l[i]==r[i]) b[l[i]]=rem[i][0];
delete [] l;
delete [] r;
delete [] rem;
delete [] moder;
}
void fast_lagrange(T x[],T y[],int m)
{
int M=4*m;
poly *moder = new poly [M];
poly *res = new poly [M];
int *l = new int [M];
int *r = new int [M];
T *val = new T [M];
memset(l,0,sizeof(int)*(M));
memset(r,0,sizeof(int)*(M));
l[1]=1,r[1]=m;
for (int i=1;i<M;i++)
{
if (l[i]==r[i]) continue;
int mid=(l[i]+r[i])/2;
l[i<<1]=l[i],r[i<<1]=mid;
l[i<<1|1]=mid+1,r[i<<1|1]=r[i];
}
for (int i=M-1;i;i--)
{
if (l[i]==r[i])
{
if (l[i])
{
moder[i]=poly(1),moder[i][0]=sub(0,x[l[i]]),moder[i][1]=1;
}
continue;
}
moder[i]=moder[i<<1]*moder[i<<1|1];
moder[i].setlength(r[i]-l[i]+1);
}
for (int i=1;i<=m;i++)
val[i]=x[i];
poly g=moder[1].der();
g.multi_eval(val,m);
for (int i=M-1;i;i--)
{
if (l[i]==r[i])
{
if (l[i])
{
res[i]=poly(0),res[i][0]=mul(y[l[i]],mod_inv(val[l[i]]));
}
continue;
}
res[i]=res[i<<1]*moder[i<<1|1]+res[i<<1|1]*moder[i<<1];
res[i].setlength(r[i]-l[i]);
}
(*this)=res[1];
delete [] l;
delete [] r;
delete [] moder;
delete [] res;
}
};
}
int n, m;
polyn f1;
LL f[N], inv[N], ff[N];
polyn pow_mod(polyn a, int e) {
polyn res;
res.setlength(0), res[0] = 1;
for (; e; a = a * a, e >>= 1) if (e & 1) res = res * a;
return res;
}
int main() {
IO;
Poly::init();
f[0] = 1;
rep(i, 1, N) f[i] = (f[i - 1] * i) % mod;
ff[1] = ff[0] = inv[1] = inv[0] = 1;
rep(i, 2, N) {
inv[i] = (LL)(mod - mod / i) * inv[mod % i] % mod;
ff[i] = inv[i];
}
rep(i, 2, N) inv[i] = (inv[i - 1] * inv[i]) % mod;
cin >> n >> m;
f1.setlength(m);
repn(i, 0, m) {
LL res = f[m] * f[m] % mod;
res = res * inv[i] % mod;
res = res * inv[m - i] % mod;
res = res * inv[m - i] % mod;
f1[i] = res;
}
f1 = pow_mod(f1, n);
LL ans = 0;
repn(i, 0, n * m) {
LL res = f1[i] * f[n * m - i];
if (i & 1) ans = (ans - res + mod) % mod;
else ans = (ans + res) % mod;
}
cout << ans << "\n";
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 16ms
memory: 77532kb
input:
2 2
output:
4
result:
ok 1 number(s): "4"
Test #2:
score: 0
Accepted
time: 36ms
memory: 76604kb
input:
5 1
output:
44
result:
ok 1 number(s): "44"
Test #3:
score: 0
Accepted
time: 35ms
memory: 77240kb
input:
167 91
output:
284830080
result:
ok 1 number(s): "284830080"
Test #4:
score: 0
Accepted
time: 45ms
memory: 77572kb
input:
2 1
output:
1
result:
ok 1 number(s): "1"
Test #5:
score: 0
Accepted
time: 26ms
memory: 77340kb
input:
2 3
output:
36
result:
ok 1 number(s): "36"
Test #6:
score: 0
Accepted
time: 42ms
memory: 78352kb
input:
2 4
output:
576
result:
ok 1 number(s): "576"
Test #7:
score: 0
Accepted
time: 34ms
memory: 77460kb
input:
3 1
output:
2
result:
ok 1 number(s): "2"
Test #8:
score: 0
Accepted
time: 29ms
memory: 78344kb
input:
3 2
output:
80
result:
ok 1 number(s): "80"
Test #9:
score: 0
Accepted
time: 30ms
memory: 76400kb
input:
3 3
output:
12096
result:
ok 1 number(s): "12096"
Test #10:
score: 0
Accepted
time: 34ms
memory: 77564kb
input:
3 4
output:
4783104
result:
ok 1 number(s): "4783104"
Test #11:
score: 0
Accepted
time: 34ms
memory: 76968kb
input:
4 1
output:
9
result:
ok 1 number(s): "9"
Test #12:
score: 0
Accepted
time: 15ms
memory: 77516kb
input:
4 2
output:
4752
result:
ok 1 number(s): "4752"
Test #13:
score: 0
Accepted
time: 24ms
memory: 78132kb
input:
4 3
output:
17927568
result:
ok 1 number(s): "17927568"
Test #14:
score: 0
Accepted
time: 41ms
memory: 76888kb
input:
4 4
output:
776703752
result:
ok 1 number(s): "776703752"
Test #15:
score: 0
Accepted
time: 37ms
memory: 77528kb
input:
5 2
output:
440192
result:
ok 1 number(s): "440192"
Test #16:
score: 0
Accepted
time: 27ms
memory: 77016kb
input:
5 3
output:
189125068
result:
ok 1 number(s): "189125068"
Test #17:
score: 0
Accepted
time: 33ms
memory: 76628kb
input:
5 4
output:
975434093
result:
ok 1 number(s): "975434093"
Test #18:
score: 0
Accepted
time: 454ms
memory: 98572kb
input:
1000 1000
output:
720037464
result:
ok 1 number(s): "720037464"
Test #19:
score: 0
Accepted
time: 25ms
memory: 78148kb
input:
72 42
output:
638177567
result:
ok 1 number(s): "638177567"
Test #20:
score: 0
Accepted
time: 41ms
memory: 77584kb
input:
15 19
output:
663050288
result:
ok 1 number(s): "663050288"
Test #21:
score: 0
Accepted
time: 32ms
memory: 77320kb
input:
68 89
output:
94365047
result:
ok 1 number(s): "94365047"
Test #22:
score: 0
Accepted
time: 26ms
memory: 77824kb
input:
92 37
output:
652605307
result:
ok 1 number(s): "652605307"
Test #23:
score: 0
Accepted
time: 39ms
memory: 77704kb
input:
61 87
output:
498277867
result:
ok 1 number(s): "498277867"
Test #24:
score: 0
Accepted
time: 23ms
memory: 78244kb
input:
81 40
output:
133095344
result:
ok 1 number(s): "133095344"
Test #25:
score: 0
Accepted
time: 36ms
memory: 77308kb
input:
7 91
output:
524164813
result:
ok 1 number(s): "524164813"
Test #26:
score: 0
Accepted
time: 20ms
memory: 78164kb
input:
31 18
output:
361233485
result:
ok 1 number(s): "361233485"
Test #27:
score: 0
Accepted
time: 38ms
memory: 77604kb
input:
74 54
output:
500686087
result:
ok 1 number(s): "500686087"
Test #28:
score: 0
Accepted
time: 29ms
memory: 78396kb
input:
32 2
output:
586504335
result:
ok 1 number(s): "586504335"
Test #29:
score: 0
Accepted
time: 305ms
memory: 93356kb
input:
656 718
output:
346764298
result:
ok 1 number(s): "346764298"
Test #30:
score: 0
Accepted
time: 124ms
memory: 82688kb
input:
254 689
output:
358078813
result:
ok 1 number(s): "358078813"
Test #31:
score: 0
Accepted
time: 333ms
memory: 93808kb
input:
713 674
output:
914437613
result:
ok 1 number(s): "914437613"
Test #32:
score: 0
Accepted
time: 88ms
memory: 81704kb
input:
136 698
output:
56687290
result:
ok 1 number(s): "56687290"
Test #33:
score: 0
Accepted
time: 120ms
memory: 81524kb
input:
369 401
output:
312325811
result:
ok 1 number(s): "312325811"
Test #34:
score: 0
Accepted
time: 59ms
memory: 78636kb
input:
280 204
output:
280012063
result:
ok 1 number(s): "280012063"
Test #35:
score: 0
Accepted
time: 120ms
memory: 81108kb
input:
904 225
output:
162909174
result:
ok 1 number(s): "162909174"
Test #36:
score: 0
Accepted
time: 433ms
memory: 95424kb
input:
855 928
output:
39885159
result:
ok 1 number(s): "39885159"
Test #37:
score: 0
Accepted
time: 123ms
memory: 81120kb
input:
503 365
output:
745115888
result:
ok 1 number(s): "745115888"
Test #38:
score: 0
Accepted
time: 369ms
memory: 95484kb
input:
646 996
output:
610925577
result:
ok 1 number(s): "610925577"
Test #39:
score: 0
Accepted
time: 432ms
memory: 96064kb
input:
990 918
output:
203469632
result:
ok 1 number(s): "203469632"
Test #40:
score: 0
Accepted
time: 440ms
memory: 100204kb
input:
961 949
output:
169566857
result:
ok 1 number(s): "169566857"
Test #41:
score: 0
Accepted
time: 441ms
memory: 97604kb
input:
946 932
output:
352423195
result:
ok 1 number(s): "352423195"
Test #42:
score: 0
Accepted
time: 428ms
memory: 96192kb
input:
903 981
output:
196309824
result:
ok 1 number(s): "196309824"
Test #43:
score: 0
Accepted
time: 441ms
memory: 95832kb
input:
916 988
output:
487208972
result:
ok 1 number(s): "487208972"
Test #44:
score: 0
Accepted
time: 429ms
memory: 100808kb
input:
982 982
output:
387421488
result:
ok 1 number(s): "387421488"
Test #45:
score: 0
Accepted
time: 466ms
memory: 101016kb
input:
955 911
output:
955637031
result:
ok 1 number(s): "955637031"
Test #46:
score: 0
Accepted
time: 437ms
memory: 96312kb
input:
906 999
output:
798469943
result:
ok 1 number(s): "798469943"
Test #47:
score: 0
Accepted
time: 447ms
memory: 100108kb
input:
982 975
output:
193506289
result:
ok 1 number(s): "193506289"
Test #48:
score: 0
Accepted
time: 434ms
memory: 96172kb
input:
921 991
output:
431202149
result:
ok 1 number(s): "431202149"