#pragma once
namespaceKaratsubaImpl{template<typenameT>vector<T>naive(constvector<T>&a,constvector<T>&b){if(a.empty()andb.empty())return{};if(a.size()<b.size())returnnaive(b,a);ints=a.size(),t=b.size();vector<T>c(s+t-1);for(inti=0;i<s;i++){for(intj=0;j<t;j++)c[i+j]+=a[i]*b[j];}returnc;}template<typenameT>voidadd(vector<T>&a,constvector<T>&b){if(a.size()<b.size())a.resize(b.size());for(inti=0;i<(int)b.size();i++)a[i]+=b[i];}template<typenameT>voidsub(vector<T>&a,constvector<T>&b){if(a.size()<b.size())a.resize(b.size());for(inti=0;i<(int)b.size();i++)a[i]-=b[i];}template<typenameT>vector<T>karatsuba(constvector<T>&a,constvector<T>&b){if(a.empty()andb.empty())return{};if(a.size()<b.size())returnkaratsuba(b,a);if(a.size()<32)returnnaive(a,b);intd=a.size()/2;vector<T>al{begin(a),begin(a)+d},au{begin(a)+d,end(a)};if((int)b.size()<d+10){autocl=karatsuba(al,b);autocu=karatsuba(au,b);vector<T>c(a.size()+b.size()-1);for(inti=0;i<(int)cl.size();i++)c[i]=cl[i];for(inti=0;i<(int)cu.size();i++)c[i+d]+=cu[i];returnc;}vector<T>bl{begin(b),begin(b)+d},bu{begin(b)+d,end(b)};vector<T>alu{al},blu{bl};add(alu,au),add(blu,bu);autoc_ll=karatsuba(al,bl);autocuu=karatsuba(au,bu);autoclu=karatsuba(alu,blu);sub(clu,c_ll),sub(clu,cuu);vector<T>c(d);copy(begin(clu),end(clu),back_inserter(c));c.resize(a.size()+b.size()-1);add(c,c_ll);for(inti=0;i<(int)cuu.size();i++)c[i+2*d]+=cuu[i];c.resize(a.size()+b.size()-1);returnc;}}// namespace KaratsubaImplusingKaratsubaImpl::karatsuba;