#include<cstdio>
#include<cstdlib>
#include<utility>
#include<type_traits>
/**
* 宗旨:
* 不排斥STL,不追求最小的常数,力争通用化,不过度检查错误
* ----------------------------------------------------------------------------------
* 匿名的namespace一般是define
* Base_Tools是常用板子
* Math_Tools是偏数学的板子
* IO是读写优化
* rel_ops其实跟标准库的基本一个用法,但是模板参传了俩
* 现在这份缺省源已经缩减,啊不,长回为23kb了……
* (慢得要死)
* 经过了删减,只保留了觉得写得还行的板子
* 添加了一些内建函数有关,同时std::enable_if限制了一些函数
* 然后发现auto的泛型就是默认上抬……算了就这样。
* 泛型auto……LQ你越来越离谱了。
* “你是写开发的吗?”啊也许以后是写库的
* todo:
* modInt更好用。
* frac写好。
* learn Poly
* 修锅基排
* 重写IO,判EOF
*/
namespace QL{
namespace{
#define sqrt __builtin_sqrt
#define sqrtf __builtin_sqrtf
#define sqrtl __builtin_sqrtl
#define ceil __builtin_ceil
#define ceilf __builtin_ceilf
#define ceill __builtin_ceill
#define floor __builtin_floor
#define floorf __builtin_floorf
#define floorl __builtin_floorl
#define memset __builtin_memset
#define memcpy __builtin_memcpy
#define strlen __builtin_strlen
#define strcmp __builtin_strcmp
#define fwrite __builtin_fwrite
#define putchar __builtin_putchar
#define fputc __builtin_fputc
#define fputs __builtin_fputs
#define log2 __builtin_log2
#define log __builtin_log
#define cos __builtin_cos
#define sin __builtin_sin
#define tan __builtin_tan
#define acos __builtin_acos
#ifndef likely
#define likely(x) __builtin_expect(!!(x),1)
#endif
#ifndef unlikely
#define unlikely(x) __builtin_expect(!!(x),0)
#endif
}
namespace Error{
constexpr void make_re(int _seed_=114514){
std::exit(_seed_);
}
#ifndef assert
constexpr bool assert(bool x,const char *reason){
if(unlikely(!x)){
fputs(reason,stderr);
fputs(reason,stdout);
make_re();
}
return false;
}
constexpr bool assert(bool x,char *reason){
return assert(x,const_cast<const char *>(reason));
}
constexpr bool assert(bool x){
if(unlikely(!x)){
fputs("Assert: RE",stderr);
fputs("Assert: RE",stdout);
make_re();
}
return false;
}
#endif
}
namespace rel_ops{
namespace Calc{
template<typename _Tp1,typename _Tp2>
constexpr _Tp1 operator+=(_Tp1 &lhs,const _Tp2 &rhs){
return lhs=(lhs+rhs);
}
template<typename _Tp1,typename _Tp2>
constexpr _Tp1 operator-=(_Tp1 &lhs,const _Tp2 &rhs){
return lhs=(lhs-rhs);
}
template<typename _Tp1,typename _Tp2>
constexpr _Tp1 operator*=(_Tp1 &lhs,const _Tp2 &rhs){
return lhs=(lhs*rhs);
}
template<typename _Tp1,typename _Tp2>
constexpr _Tp1 operator/=(_Tp1 &lhs,const _Tp2 &rhs){
return lhs=(lhs/rhs);
}
template<typename _Tp1,typename _Tp2>
constexpr _Tp1 operator%=(_Tp1 &lhs,const _Tp2 &rhs){
return lhs=(lhs%rhs);
}
template<typename _Tp1,typename _Tp2>
constexpr _Tp1 operator&=(_Tp1 &lhs,const _Tp2 &rhs){
return lhs=(lhs&rhs);
}
template<typename _Tp1,typename _Tp2>
constexpr _Tp1 operator|=(_Tp1 &lhs,const _Tp2 &rhs){
return lhs=(lhs|rhs);
}
template<typename _Tp1,typename _Tp2>
constexpr _Tp1 operator^=(_Tp1 &lhs,const _Tp2 &rhs){
return lhs=(lhs^rhs);
}
}
namespace Compare{
template<typename _Tp1,typename _Tp2>
constexpr bool operator!=(const _Tp1 &lhs,const _Tp2 &rhs){
return !(lhs==rhs);
}
template<typename _Tp1,typename _Tp2>
constexpr bool operator<=(const _Tp1 &lhs,const _Tp2 &rhs){
return (lhs==rhs)||(lhs<rhs);
}
template<typename _Tp1,typename _Tp2>
constexpr bool operator>(const _Tp1 &lhs,const _Tp2 &rhs){
return !((lhs==rhs)||(lhs<rhs));
}
template<typename _Tp1,typename _Tp2>
constexpr bool operator>=(const _Tp1 &lhs,const _Tp2 &rhs){
return !(lhs<rhs);
}
}
}
namespace Base_Tools{
#if _GLIBCXX_NUMERIC&&(__cplusplus>=201703L)
template<typename _Tp>
constexpr _Tp Inf=std::numeric_limits<_Tp>::max()/2;
#else
constexpr int Inf=0x3f3f3f3f;
constexpr long long llInf=0x3f3f3f3f3f3f3f3f;
constexpr double dbInf=1e17;
constexpr long double ldInf=1e22;
#endif
using ll=long long;
using ull=unsigned long long;
using ui=unsigned int;
using db=double;
using ld=long double;
#if _GLIBCXX_USE_INT128
using lll=__int128;
using ulll=unsigned __int128;
#else
using lll=long long;
using ulll=unsigned long long;
#endif
template<typename _Tp1,typename _Tp2>
constexpr auto min(_Tp1 x,_Tp2 y){
return x<y?x:y;
}
template<typename _Tp,typename ...Args>
constexpr auto min(_Tp x,Args ...args){
return min(x,min(args...));
}
template<typename _Tp1,typename _Tp2>
constexpr auto max(_Tp1 x,_Tp2 y){
return y<x?x:y;
}
template<typename _Tp,typename ...Args>
constexpr auto max(_Tp x,Args ...args){
return max(x,max(args...));
}
template<typename _Tp1,typename _Tp2>
constexpr bool chkmin(_Tp1 &x,_Tp2 y){
return y<x?(x=y,true):false;
}
template<typename _Tp1,typename _Tp2,typename...Args>
constexpr bool chkmin(_Tp1 &x,_Tp2 y,Args ...args){
return chkmin(x,y)|chkmin(x,args...);
}
template<typename _Tp1,typename _Tp2>
constexpr bool chkmax(_Tp1 &x,_Tp2 y){
return x<y?(x=y,true):false;
}
template<typename _Tp1,typename _Tp2,typename...Args>
constexpr bool chkmax(_Tp1 &x,_Tp2 y,Args ...args){
return chkmax(x,y)|chkmax(x,args...);
}
template<typename _Tp>
class has_member_swap{
private:
template<typename T>
static auto Check(int)->decltype(std::declval<T>().swap(),std::true_type());
template<typename T>
static std::false_type Check(...);
public:
enum{value=std::is_same<decltype(Check<_Tp>(0)),std::true_type>::value};
};
template<typename _Tp>
constexpr void swap(_Tp &x,_Tp &y){
_Tp tmp;
tmp=x,x=y,y=tmp;
}
template<>
constexpr void swap(int &x,int &y){
x!=y&&(x^=y^=x^=y);
}
template<typename _Tp>
constexpr void swap(_Tp *&x,_Tp *&y){
_Tp *tmp;
tmp=x,x=y,y=tmp;
}
template<typename _Tp>
constexpr void swap(_Tp &x,_Tp &y,typename std::enable_if<has_member_swap<_Tp>::value,void>::type* =nullptr){
x.swap(y);
}
template<typename _Tp>
constexpr _Tp abs(const _Tp &x){
return x<0?-x:x;
}
}
/*
gcd和lcm会把非整数的gcd当作1
Math_Tools_Base是实现,有些地方接口改了一下,就多套了一层
*/
namespace Math_Tools{
namespace Math_Tools_base{
template<typename _Tp,typename _Used>
constexpr _Tp qpow(Base_Tools::ll x,_Used p,_Tp mod){
_Tp ret=1;
for(;p;p>>=1,x=x*x%mod) if(p&1) ret=ret*x%mod;
return ret;
}
}
template<typename _Tp,typename _Used>
constexpr _Tp qpow(_Tp x,_Used p,_Tp mod){
return Math_Tools_base::qpow(x,p,mod);
}
template<typename _Tp>
constexpr _Tp inv(_Tp x,_Tp mod){
return Math_Tools_base::qpow(x,mod-2,mod);
}
template<typename _Tp>
constexpr auto gcd(_Tp a,_Tp b,typename std::enable_if<std::is_integral<_Tp>::value,void>::type* =nullptr){
return b?gcd(b,a%b):a;
}
template<typename _Tp>
constexpr auto gcd(_Tp a,_Tp b,typename std::enable_if<std::is_floating_point<_Tp>::value,void>::type* =nullptr){
return 1;
}
template<typename _Tp>
constexpr auto lcm(_Tp a,_Tp b){
return a/gcd(a,b)*b;
}
}
/**
* 本实现的亮点是支持不定模数(不用遍历地进行初始化)
* 需要实现一个类,重载const类型的()运算符返回模数
* 实现可参考QL::ModNumber::Moder
* 模数有问题可以重载inv
* 其他的不知道了,似乎不是很快,要卡常的可以套约减器
* (用这玩意儿也就图个方便)
* upd:塞进去了个barrett约减,更慢了(乐
* 跑不过编译器优化,它是蒙哥马利吗……
*/
namespace ModNumber{
using Base_Tools::ll;
using Base_Tools::ulll;
template<typename _Tp>
struct Barrett{
_Tp mod;
ulll used;
Barrett(){}
Barrett(_Tp _mod):mod{_mod},used{(ulll(1)<<63)/mod}{}
constexpr void reset(_Tp _mod){
mod=_mod;
used=(ulll(1)<<63)/mod;
}
constexpr _Tp calc(ll x)const{
return (x=x-mod*((x*used)>>63))<mod?x:x-mod;
}
};
template<typename _Tp>
struct Moder{
template<typename _Tp_>
constexpr void chk_val(_Tp_ &val)const{
val<0?(val+=getmod()):(val<getmod()?0:val-=getmod());
}
virtual const _Tp getmod(void)const{
return _Tp(998244353);
}
virtual const _Tp operator()(void)const{
return getmod();
}
virtual const _Tp calc(ll x)const{
return x%getmod();
}
template<typename _Tp1,typename _Tp2>
constexpr _Tp plus(const _Tp1 &x,const _Tp2 &y)const{
return calc(x+y);
}
template<typename _Tp1,typename _Tp2>
constexpr _Tp mul(const _Tp1 &x,const _Tp2 &y)const{
return calc(ll(x)*y);
}
constexpr _Tp qpow(ll a,int x)const{
_Tp ret=1;
for(;x;x>>=1,a=calc(a*a)) if(x&1) ret=calc(ret*a);
return ret;
}
template<typename _Tp_>
constexpr _Tp inv(const _Tp_ &x)const{
return qpow(x,getmod()-2);
}
};
template<typename _Moder>
class modInt{
protected:
static _Moder mod;
int v;
public:
constexpr modInt():v{}{}
template<typename _Tp_>
constexpr modInt(const _Tp_ &_v):v(_v%mod()){mod.chk_val(v);}
template<typename _Tp_>
constexpr explicit operator _Tp_()const{
return _Tp_(v);
}
constexpr modInt operator-()const{
return modInt(mod()-v);
}
constexpr modInt operator+(const modInt &y)const{
return mod.plus(v,y.v);
}
constexpr modInt operator-(const modInt &y)const{
return *this+(-y);
}
constexpr modInt operator*(const modInt &y)const{
return mod.mul(v,y.v);
}
constexpr modInt operator/(const modInt &y)const{
return mod.mul(v,mod.inv(y.v));
}
template<typename _Tp_>
constexpr modInt operator^(const modInt<_Tp_> &y)const{
return mod.qpow(v,int(y));
}
template<typename _Tp_>
constexpr friend modInt operator+(const _Tp_ &x,const modInt &y){
return mod.plus(x,y.v);
}
template<typename _Tp_>
constexpr friend modInt operator+(const modInt &x,const _Tp_ &y){
return mod.plus(x.v,y);
}
template<typename _Tp_>
constexpr friend modInt operator-(const _Tp_ &x,const modInt &y){
return x+(-y);
}
template<typename _Tp_>
constexpr friend modInt operator-(const modInt &x,const _Tp_ &y){
return x+(-y);
}
template<typename _Tp_>
constexpr friend modInt operator*(const _Tp_ &x,const modInt &y){
return mod.mul(x,y.v);
}
template<typename _Tp_>
constexpr friend modInt operator*(const modInt &x,const _Tp_ &y){
return mod.mul(x.v,y);
}
template<typename _Tp_>
constexpr friend modInt operator/(const _Tp_ &x,const modInt &y){
return mod.mul(x,mod.inv(y.v));
}
template<typename _Tp_>
constexpr friend modInt operator/(const modInt &x,const _Tp_ &y){
return mod.mul(x.v,mod.inv(y));
}
template<typename _Tp_>
constexpr friend modInt operator^(const modInt &x,const _Tp_ &y){
return mod.qpow(x.v,y);
}
template<typename _Tp_>
constexpr friend bool operator<(const _Tp_ &x,const modInt &y){
return x<y.v;
}
template<typename _Tp_>
constexpr bool operator<(const _Tp_ &y)const{
return v<y;
}
template<typename _Tp_>
constexpr friend bool operator==(const _Tp_ &x,const modInt &y){
return x==y.v;
}
template<typename _Tp_>
constexpr bool operator==(const _Tp_ &y)const{
return v==y;
}
constexpr modInt &operator++(){
mod.chk_val(++v);
return *this;
}
constexpr modInt operator++(int){
modInt ret=*this;
mod.chk_val(++v);
return ret;
}
constexpr modInt &operator--(){
mod.chk_val(--v);
return *this;
}
constexpr modInt operator--(int){
modInt ret=*this;
mod.chk_val(--v);
return ret;
}
};
template<typename _Moder>
_Moder modInt<_Moder>::mod;
}
/**
* 一个不成型的东西
* 日后补全
*/
namespace FracNumber{
using Math_Tools::lcm;
using Math_Tools::gcd;
template<typename _Tp>
class frac{
protected:
_Tp x,y;
constexpr void chk_self(){
_Tp _gcd_=gcd(x,y);
if(_gcd_!=1) x/=_gcd_,y/=_gcd_;
}
public:
constexpr frac():x{},y{}{}
template<typename T>
constexpr frac(T num,typename std::enable_if<std::is_integral<T>::value,void>::type* =nullptr):x(num),y(1){}
template<typename T>
constexpr frac(T _x,T _y,typename std::enable_if<std::is_integral<T>::value,void>::type* =nullptr):x(_x),y(_y){chk_self();}
template<typename T>
constexpr explicit operator T()const{
return T(x)/y;
}
template<typename T>
constexpr bool operator<(const frac<T> &it)const{
auto _lcm_=lcm(y,it.y);
return x*(_lcm_/y)<it.x*(_lcm_/it.y);
}
};
}
/**
* 多项式,占坑
* 以后会尽量补全的
*/
namespace ComplexNumber{
template<typename _Tp>
struct complex{
_Tp real,imag;
constexpr complex():real{},imag{}{}
template<typename T>
constexpr complex(T _real):real(_real),imag{}{}
template<typename T1,typename T2>
constexpr complex(T1 _real,T2 _imag):real(_real),imag(_imag){}
constexpr complex operator+(const complex &it)const{
return complex(real+it.real,imag+it.imag);
}
constexpr complex operator-(const complex &it)const{
return complex(real-it.real,imag-it.imag);
}
constexpr complex operator*(const complex &it)const{
return complex(real*it.real-imag*it.imag,imag*it.real+real*it.imag);
}
};
}
namespace Poly_Tools{
/**
* 暴力乘法(划掉)
* upd:FFT
* waring:多线程(指,多个线程同时使用这个板子,分别进行多项式运算)会寄(谁特么放这种东西进多线程)
*/
using Base_Tools::ui;
using Base_Tools::db;
using Base_Tools::swap;
using Base_Tools::max;
using Complex=ComplexNumber::complex<db>;
using namespace rel_ops::Calc;
namespace Poly_Helper{
static constexpr ui max_len=2<<20;
ui r[max_len];
constexpr void reset(int x){
for(int i=0;i<x;++i) r[i]=(r[i>>1]>>1)|((i&1)?(x>>1):0);
}
constexpr ui pw[]{0,1,2,4,8,16,32,64,128,256,512,1024};
constexpr ui to_up(ui x){
#define cs(x) case pw[x] ... pw[x+1]-1: return pw[x+1];
switch(x){
cs(0)cs(1)cs(2)cs(3)cs(4)cs(5)cs(6)cs(7)cs(8)cs(9)cs(10)
default: return 1u<<(32-__builtin_clz(x));
}
#undef cs
}
constexpr db PI=acos(-1);
constexpr void clear(Complex *f,ui x){
for(ui i(0);i<x;++i) f[i]=Complex();
}
constexpr void FFT(Complex *f,ui x,int type){
for(ui i(0);i<x;++i) if(i<r[i]) swap(f[i],f[r[i]]);
for(ui p(1),l(2);l<=x;p=l,l<<=1){
Complex step(cos(PI/p),type*sin(PI/p));
for(ui i=0;i<x;i+=l){
Complex *g=f+i,*h=f+i+p;
Complex w(1,0),t;
for(ui k(0);k<p;++k){
t=h[k]*w;
h[k]=g[k]-t,g[k]=g[k]+t;
w*=step;
}
}
}
}
Complex f[max_len];
}
template<typename _Tp>
class Poly{
protected:
_Tp *p;
ui n;
public:
constexpr int length(void)const{return n;}
constexpr Poly():p{},n{}{}
constexpr Poly(const ui &_n):p{new _Tp[_n]{}},n{_n}{}
constexpr Poly(const std::initializer_list<_Tp> &L){
delete[] p;
p=new _Tp[L.size()]{},n=0;
for(auto it:L) p[n++]=it;
}
constexpr void resize(const ui &_n){
delete[] p;
p=new _Tp[_n]{},n=_n;
}
constexpr Poly(const Poly &it):n{it.n}{
delete[] p;
p=new _Tp[it.n]{};
memcpy(p,it.p,sizeof(_Tp)*it.n);
}
constexpr _Tp &operator[](const ui &x){
if(x>=n) Error::make_re();
return p[x];
}
constexpr const _Tp &operator[](const ui &x)const{
if(x>=n) Error::make_re();
return p[x];
}
constexpr void FFT(Complex *f,int x,int type)const{
Poly_Helper::FFT(f,x,type);
}
constexpr Poly operator*(const Poly &it)const{
using Poly_Helper::f;
ui x=Poly_Helper::to_up(n+it.n-1);
Poly_Helper::clear(f,x);
Poly_Helper::reset(x);
for(ui i(0);i<n;++i) f[i].real=p[i];
for(ui i(0);i<it.n;++i) f[i].imag=it.p[i];
FFT(f,x,1);
for(ui i(0);i<x;++i) f[i]*=f[i];
FFT(f,x,-1);
Poly ret(n+it.n-1);
for(ui i(0);i<ret.n;++i) ret[i]=f[i].imag/x/2+0.5;
return ret;
}
};
}
/**
* 字符串的工具
*/
namespace String_Tools{
namespace SA{
template<int M=128,int N>
void calc_sa(char (&str)[N],int sa[],int rk[],int n){
int m=M-1;
static int cnt[N<M?M:N],id[N],oldrk[N<<1],key[N];
for(int i=1;i<=n;++i) ++cnt[rk[i]=str[i]];
for(int i=1;i<=m;++i) cnt[i]+=cnt[i-1];
for(int i=n;i;--i) sa[cnt[rk[i]]--]=i;
for(int k=1,p;;k<<=1,m=p){
p=0;
for(int i=n;i>n-k;--i) id[++p]=i;
for(int i=1;i<=n;++i) if(sa[i]>k) id[++p]=sa[i]-k;
memset(cnt,0,sizeof(int)*(m+1));
for(int i=1;i<=n;++i) ++cnt[key[i]=rk[id[i]]];
for(int i=1;i<=m;++i) cnt[i]+=cnt[i-1];
for(int i=n;i;--i) sa[cnt[key[i]]--]=id[i];
memcpy(oldrk,rk,sizeof(int)*(n+1));
p=0;
for(int i=1;i<=n;++i){
static auto cmp=[&k](int x,int y){
return oldrk[x]==oldrk[y]&&oldrk[x+k]==oldrk[y+k];
};
rk[sa[i]]=cmp(sa[i],sa[i-1])?p:++p;
}
if(p==n) return;
}
}
template<int N>
constexpr void calc_height(char (&str)[N],int sa[],int rk[],int height[],int n){
for(int i=1,k=0;i<=n;++i){
if(!rk[i]) continue;
k&&--k;
for(;str[i+k]==str[sa[rk[i]-1]+k];++k);
height[rk[i]]=k;
}
}
}
}
/**
* 占坑
*/
namespace Data_Structure{}
namespace Algorithm{
using Base_Tools::swap;
template<typename _Tp>
void radix_sort(_Tp *x,int n,typename std::enable_if<std::is_integral<_Tp>::value,void>::type* =nullptr){
static const int mask=(1<<8)-1;
static int *cnt=new int[mask+1],*y=new int[n+5];
for(int k=0;k<32;k+=8){
for(int i=0;i<=mask;++i) cnt[i]=0;
for(int i=1;i<=n;++i) ++cnt[(x[i]>>k)&mask];
for(int sum=0,i=0;i<=mask;++i)
sum+=cnt[i],cnt[i]=sum-cnt[i];
for(int i=1;i<=n;++i) y[++cnt[(x[i]>>k)&mask]]=x[i];
swap(x,y);
}
}
template<typename _Tp,typename _Turn>
void radix_sort(_Tp *x,int n,_Turn turn){
static const int mask=(1<<8)-1;
static int *cnt=new int[mask+1],*y=new int[n+5];
for(int k=0;k<32;k+=8){
for(int i=0;i<=mask;++i) cnt[i]=0;
for(int i=1;i<=n;++i) ++cnt[(turn(x[i])>>k)&mask];
for(int sum=0,i=0;i<=mask;++i)
sum+=cnt[i],cnt[i]=sum-cnt[i];
for(int i=1;i<=n;++i) y[++cnt[(turn(x[i])>>k)&mask]]=x[i];
swap(x,y);
}
}
template<typename _Tp>
void radix_sort(_Tp *x,int n,int (*turn)(_Tp)){
static const int mask=(1<<8)-1;
static int *cnt=new int[mask+1],*y=new int[n+5];
for(int k=0;k<32;k+=8){
for(int i=0;i<=mask;++i) cnt[i]=0;
for(int i=1;i<=n;++i) ++cnt[(turn(x[i])>>k)&mask];
for(int sum=0,i=0;i<=mask;++i)
sum+=cnt[i],cnt[i]=sum-cnt[i];
for(int i=1;i<=n;++i) y[++cnt[(turn(x[i])>>k)&mask]]=x[i];
swap(x,y);
}
}
template<typename _Iterator>
constexpr void reverse(_Iterator _st,_Iterator _ed){
--_ed;
for(;_st!=_ed;++_st,--_ed) swap(_st,_ed);
}
}
}
namespace QL{
namespace Base_Tools{
template<typename _Tp>
static constexpr std::size_t integral_length=sizeof(_Tp)*10/sizeof(int);
bool is_space(char ch){
return ch==' ';
}
#if (linux||__linux__||__linux)
bool is_eoln(char ch){
return ch=='\n'||ch=='\r';
}
#else
bool is_eoln(char ch){
return ch=='\n';
}
#endif
bool is_blank(char ch){
return is_space(ch)||is_eoln(ch);
}
bool is_digit(char ch){
switch(ch){
case '0' ... '9': return true;
default: return false;
}
}
bool is_eof(char ch){
return ch==EOF;
}
}
namespace IO{
using Base_Tools::integral_length;
using Base_Tools::is_digit;
using Base_Tools::is_space;
using Base_Tools::is_eoln;
using Base_Tools::is_blank;
using Base_Tools::is_eof;
/**
* -DLOCAL后能使用错误流,并关掉fread/fwrite
* 然而使用错误流时VScode会假CE,还不能解决
* 此外,这套IO跟C的一样,不是很方便扩展
* 正在考虑怎么改一下,大概是通过友元
* 扩充了浮点数的输出,借助了C库的sprintf,写得还有点丑,之后改
* 浮点输入写好了,同样用了读如字符串的手段,不过用了atof,会短一点(牺牲了一些精度相关)。
*/
class IOstream{
protected:
using LIST=std::initializer_list<int>;
#ifndef LOCAL
std::FILE *IN;
std::FILE *OUT;
static constexpr int SIZE=1<<15;
char buf[SIZE]{},*p1{buf},*p2{buf},obuf[SIZE]{},*p3{obuf};
public:
char pull(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,SIZE,IN),p1==p2)?(Ch=EOF):*p1++;}
void push(char ch){((p3-obuf)==SIZE&&(flush(false),0)),*p3++=ch;}
template<std::size_t L>
std::FILE *set_in(const char (&name)[L]){
static char in[L+5]={};
std::sprintf(in,"%s.in",name);
return std::fopen(in,"r");
}
template<std::size_t L>
std::FILE *set_out(const char (&name)[L]){
static char out[L+5];
std::sprintf(out,"%s.out",name);
return std::fopen(out,"w");
}
#else
protected:
public:
char pull(){return std::getchar();}
void push(char ch){putchar(ch);}
void err(char ch){fputc(ch,stderr);}
template<std::size_t L>
void set_in(const char(&name)[L]){
static char in[L+5]={};
std::sprintf(in,"%s.in",name);
std::freopen(in,"r",stdin);
}
template<std::size_t L>
void set_out(const char(&name)[L]){
static char out[L+5];
std::sprintf(out,"%s.out",name);
std::freopen(out,"w",stdout);
}
#endif
public:
#ifndef LOCAL
IOstream():IN{stdin},OUT{stdout},buf{},p1{buf},p2{buf},obuf{},p3{obuf},Ch{'\n'},outchar{&IO::IOstream::push}{}
template<std::size_t L>
IOstream(const char(&name)[L]):IN{set_in(name)},OUT{set_out(name)},buf{},p1{buf},p2{buf},obuf{},p3{obuf},Ch{'\n'},outchar{&IO::IOstream::push}{}
template<std::size_t L>
IOstream(const char(&name)[L],bool in,bool out):IN{in?set_in(name):stdin},OUT{out?set_out(name):stdout},buf{},p1{buf},p2{buf},obuf{},p3{obuf},Ch{'\n'},outchar{&IO::IOstream::push}{}
template<std::size_t L>
IOstream(char(&name)[L]):IN{set_in(name)},OUT{set_out(name)},buf{},p1{buf},p2{buf},obuf{},p3{obuf},Ch{'\n'},outchar{&IO::IOstream::push}{}
template<std::size_t L>
IOstream(char(&name)[L],bool in,bool out):IN{in?set_in(name):stdin},OUT{out?set_out(name):stdout},buf{},p1{buf},p2{buf},obuf{},p3{obuf},Ch{'\n'},outchar{&IO::IOstream::push}{}
~IOstream(){flush();}
void flush(bool _flush_=false){
if(likely(p3!=obuf))
fwrite(obuf,1,p3-obuf,OUT),p3=obuf;
if(_flush_) std::fflush(stdout);
}
#else
IOstream(){}
template<std::size_t L>
IOstream(const char(&name)[L]):Ch{'\n'}{reset_stdin(name),reset_stdout(name);}
template<std::size_t L>
IOstream(const char(&name)[L],bool in,bool out):Ch{'\n'}{in&&(reset_stdin(name),0),out&&(reset_stdout(name),0);}
template<std::size_t L>
IOstream(char(&name)[L]):Ch{'\n'}{reset_stdin(name),reset_stdout(name);}
template<std::size_t L>
IOstream(char(&name)[L],bool in,bool out):Ch{'\n'}{in&&(reset_stdin(name),0),out&&(reset_stdout(name),0);}
void flush(){std::fflush(stdout);}
#endif
template<typename T>
T read(){
T x;
read(x);
return x;
}
protected:
char Ch='\n';
public:
bool eof(void)const{
return Ch==EOF;
}
template<typename T>
void read(T &&x,typename std::enable_if<std::is_integral<T>::value,void>::type* =nullptr,typename std::enable_if<std::is_signed<T>::value,void>::type* =nullptr){
x=0;bool flag=0;
for(;!is_digit(Ch)&&!is_eof(Ch);Ch=pull()) if(Ch=='-') flag=1;
if(is_eof(Ch)) return;
if(flag) for(;is_digit(Ch);Ch=pull()) x=x*10-(Ch&15);
else for(;is_digit(Ch);Ch=pull()) x=x*10+(Ch&15);
}
template<typename T>
void read(T &&x,typename std::enable_if<std::is_integral<T>::value,void>::type* =nullptr,typename std::enable_if<std::is_unsigned<T>::value,void>::type* =nullptr){
x=0;
for(;!is_digit(Ch)&&!is_eof(Ch);Ch=pull());
if(is_eof(Ch)) return;
for(;is_digit(Ch);Ch=pull()) x=x*10+(Ch&15);
}
void read(char *str){
for(;is_blank(Ch);Ch=pull());
if(is_eof(Ch)) return (void)(*str='\0');
for(;!is_blank(Ch)&&!is_eof(Ch);Ch=pull()) *str++=Ch;
*str='\0';
}
void read(char &c){
c=Ch;
for(;is_blank(c)&&!is_eof(c);c=pull());
if(is_eof(c)) return;
Ch=pull();
}
void read(bool &x){
for(;Ch!='0'&&Ch!='1'&&!is_eof(Ch);Ch=pull());
if(is_eof(Ch)) return void(x=false);
x=Ch=='1';
Ch=pull();
}
template<typename T>
void read(T &&x,typename std::enable_if<std::is_floating_point<T>::value,void*>::type* =nullptr){
static char str[114];
read(str);
x=std::atof(str);
}
template<typename T>
void read(T &x){read(std::move(x));}
protected:
void(IOstream::*outchar)(char)=&IO::IOstream::push;
template<typename T>
void out(T x,typename std::enable_if<std::is_integral<T>::value,void>::type* =nullptr,typename std::enable_if<std::is_signed<T>::value,void>::type* =nullptr){
static char sta[integral_length<T>];
int top=0;
if(x<0){
(this->*outchar)('-');
do sta[top++]=((-x)%10)|48,x/=10;
while(x);
}
else{
do sta[top++]=(x%10)|48,x/=10;
while(x);
}
while(top) (this->*outchar)(sta[--top]);
}
template<typename T>
void out(T x,typename std::enable_if<std::is_integral<T>::value,void>::type* =nullptr,typename std::enable_if<std::is_unsigned<T>::value,void>::type* =nullptr){
static char sta[integral_length<T>];
int top=0;
do sta[top++]=(x%10)|48,x/=10;
while(x);
while(top) (this->*outchar)(sta[--top]);
}
void out(bool x){(this->*outchar)(x?'1':'0');}
void out(char x){(this->*outchar)(x);}
void out(char *str){
out(reinterpret_cast<const char *>(str));
}
void out(const char *str){
while(*str!='\0') (this->*outchar)(*str++);
}
/**
* 这里很烦人,主要是ssprintf我要写几个不同的参数。
* 之后想办法干掉,大概又是套模版。
*/
void out(float x){
static char str[114];
std::sprintf(str,"%f",x);
out(str);
}
void out(double x){
static char str[114];
std::sprintf(str,"%f",x);
out(str);
}
void out(long double x){
static char str[114];
std::sprintf(str,"%Lf",x);
out(str);
}
void out(std::pair<int,float> x){
static char str[114],opt[10];
std::sprintf(opt,"%%.%df",x.first);
std::sprintf(str,opt,x.second);
out(str);
}
void out(std::pair<int,double> x){
static char str[114],opt[10];
std::sprintf(opt,"%%.%df",x.first);
std::sprintf(str,opt,x.second);
out(str);
}
void out(std::pair<int,long double> x){
static char str[114],opt[10];
std::sprintf(opt,"%%.%dLf",x.first);
std::sprintf(str,opt,x.second);
out(str);
}
void set_std_out(){outchar=&IO::IOstream::push;}
#ifdef LOCAL
void set_err_out(){outchar=&IO::IOstream::err;}
#endif
public:
template<typename...Args>
void read(Args &&...args){(void)LIST{(read(args),0)...};}
template<typename...Args>
void write(Args...args){set_std_out(),(void)LIST{(out(args),0)...};}
template<typename...Args>
void writeln(Args...args){write(args...),push('\n');}
#ifdef LOCAL
template<typename...Args>
void error(Args...args){set_err_out(),(void)LIST{(out(args),0)...};}
template<typename...Args>
void errorln(Args...args){error(args...),err('\n');}
#endif
};
IOstream lq;
}
}
namespace MAIN{
using QL::IO::lq;
using QL::Poly_Tools::Poly;
using namespace QL::rel_ops::Calc;
constexpr int N=1<<20;
int n,m;
Poly<int> f,g;
signed _main_(){
lq.read(n,m);
f.resize(n+1);
g.resize(m+1);
for(int i=0;i<=n;++i) lq.read(f[i]);
for(int i=0;i<=m;++i) lq.read(g[i]);
f=f*g;
for(int i=0;i<f.length();++i) lq.write(f[i],' ');
return 0;
}
}
signed main(){
return MAIN::_main_();
}
Compilation | N/A | N/A | Compile OK | Score: N/A | 显示更多 |
Subtask #1 Testcase #1 | 19.52 us | 96 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #2 | 27.806 ms | 8 MB + 40 KB | Accepted | Score: 100 | 显示更多 |
Subtask #1 Testcase #3 | 11.455 ms | 3 MB + 648 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #4 | 11.533 ms | 3 MB + 636 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #5 | 20.37 us | 96 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #6 | 20.21 us | 96 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #7 | 19.23 us | 96 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #8 | 26.636 ms | 7 MB + 528 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #9 | 26.613 ms | 7 MB + 528 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #10 | 25.493 ms | 6 MB + 1012 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #11 | 28.015 ms | 8 MB + 120 KB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #12 | 23.934 ms | 7 MB | Accepted | Score: 0 | 显示更多 |
Subtask #1 Testcase #13 | 18.87 us | 96 KB | Accepted | Score: 0 | 显示更多 |