小Q与进位制 - 分治FFT

题目大意:有一种进制,第i位的进位值是 basei b a s e i ,然后现在给你一个数字a,问有多少数字不超过a,保证a有n位且最高位不为0, n120000 n ≤ 120000
题解:答案是: ni=1aijibj ∑ i = 1 n a i ∏ j ≤ i b j ,考虑将a和b的每一项理解为多项式去做分治法法塔,像维护哈希一样维护b的乘积和答案即可。

#include
#include
#include
#include
#include
#include
#include
#define lint long long
#define db long double
#define gc getchar()
#define N 130000
#define BAS 100000//10000000
#define debug(x) cerr<<#x<<"="<
#define sp <<" "
#define ln <
using namespace std;
const db PI=acos(-1);
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
struct E{
    db x,y;E(db _x=0,db _y=0) { x=_x,y=_y; }
    inline E operator+(const E &b)const { return E(x+b.x,y+b.y); }
    inline E operator+=(const E &b) { return (*this)=(*this)+b; }
    inline E operator-(const E &b)const { return E(x-b.x,y-b.y); }
    inline E operator*(const E &b)const { return E(x*b.x-y*b.y,x*b.y+y*b.x); }
    inline E operator*=(const E &b) { return (*this)=(*this)*b; }
};int r[N<<4];vector a[N],b[N],t1,t2;
inline int show(vector &a,int t=1)//type = 0 : show number;else show polygon
{
    int n=(int)a.size();
    if(!t)
    {
        printf("%d",(int)a[n-1].x);
        for(int i=n-2;i>=0;i--)
            printf("%05d",(int)a[i].x);//////////////////////////////////////////////////////////////////////////////////////////////////////
        return printf("\n"),0;
    }
    for(int i=0;icerr<<(int)a[i].x sp;cerr ln;return 0;
}
inline int FFT(vector &a,int n,int sgn)
{
    for(int i=1;iif(i>r[i]) swap(a[i],a[r[i]]);
    for(int i=1;i1)
    {
        E wn(cos(PI/i),sgn*sin(PI/i));
        for(int j=0,t=i<<1;j1,0);
            for(int k=0;kif(sgn<0) for(int i=0;ireturn 0;
}
inline int tms(vector &a,vector &b,vector &c)
{
    int m1=(int)a.size(),m2=(int)b.size(),n=1,L=0;for(;n1;n<<=1,L++);
    for(int i=1;i>1]>>1)|((i&1)<<(L-1));
    t1.resize(n);for(int i=0;i0,0));
    t2.resize(n);for(int i=0;i0,0));
    FFT(t1,n,1),FFT(t2,n,1);for(int i=0;i1),c.resize(m1+m2-1);for(int i=0;i1;i++) c[i]=t1[i];
    return 0;
}
vector clt;
int cc=0;
inline int cl(vector &a)
{
    lint jw=0;int n=(int)a.size();clt.resize(n);
    for(int i=0;i0.5);
    for(int i=0;iwhile(jw) clt.push_back(jw%BAS),jw/=BAS,n++;
    while(n>0&&!clt[n-1]) n--;if(!n) n=1,clt[0]=0;a.resize(n);
    for(int i=0;i0);return 0;
}
inline int solve(int l,int r)
{
    if(l==r) return 0;int mid=(l+r)>>1;solve(l,mid),solve(mid+1,r);
    tms(b[l],a[mid+1],a[mid+1]),tms(b[l],b[mid+1],b[l]);
    int L=(int)a[l].size(),R=(int)a[mid+1].size(),k=max(L,R);
    a[l].resize(k);for(int i=L;i0,0);
    a[r].resize(k);for(int i=R;i1][i]=E(0,0);
    for(int i=0;i<(int)a[l].size();i++) a[l][i]+=a[mid+1][i];
    cl(a[l]),cl(b[l]);
    return 0;
}
int main()
{
    int n=inn();
    for(int i=1;i<=n;i++) b[i].push_back(inn()),cl(b[i]);
    for(int i=1;i<=n;i++) a[i].push_back(inn()),cl(a[i]);
    return solve(1,n),show(a[1],0),0;
}

你可能感兴趣的:(分治,快速傅里叶变换)