Luogu P4546 [THUWC2017]在美妙的數學王國中暢游


題意

題意奇奇怪怪,這里就不寫了。

\(\texttt{Data Range:}1\leq n\leq 10^5,1\leq m\leq 2\times 10^5\)

題解

為什么你們都是卡在數學方面,難道只有我卡在不曉得怎么維護上面嗎

看到下面的題解通篇的泰勒展開,我決定寫一篇從 \(\texttt{EGF}\) 上說明的題解,而且公式也比下面的清晰的多。

首先我們做個熱身,先來看 \(e^x,\sin x,\cos x\) 對應的 \(\texttt{EGF}\)

\[e^x=\sum\limits_{i=0}^{\infty}\frac{x^i}{i!} \]

\[\sin x=\sum\limits_{i=0}^{\infty}\frac{(-1)^ix^{2i+1}}{(2i+1)!} \]

\[\cos x=\sum\limits_{i=0}^{\infty}\frac{(-1)^ix^{2i}}{(2i)!} \]

接下來我們用 \(ax\) 替換 \(x\) 得到:

\[e^{ax}=\sum\limits_{i=0}^{\infty}\frac{a^ix^i}{i!} \]

\[\sin (ax)=\sum\limits_{i=0}^{\infty}\frac{(-1)^ia^{2i+1}x^{2i+1}}{(2i+1)!} \]

\[\cos (ax)=\sum\limits_{i=0}^{\infty}\frac{(-1)^ia^{2i}x^{2i}}{(2i)!} \]

如果寫的更直觀一點呢?

\[e^{ax}=1+ax+\frac{a^2x^2}{2!}+\frac{a^3x^3}{3!}+\cdots \]

\[\sin(ax)=ax-\frac{a^3x^3}{3!}+\frac{a^5x^5}{5!}-\frac{a^7x^7}{7!}+\cdots \]

\[\cos(ax)=1-\frac{a^2x^2}{2!}+\frac{a^4x^4}{4!}-\frac{a^6x^6}{6!}+\cdots \]

接下來就是正題了。

考慮到 \(e^{ax+b}=e^{ax}\cdot e^{b}\),而 \(b\) 是給定常數,所以

\[e^{ax+b}=e^b(1+ax+\frac{a^2x^2}{2!}+\frac{a^3x^3}{3!}+\cdots)=\sum\limits_{i=0}^{\infty}\frac{e^ba^ix^i}{i!} \]

然后根據常見的三角恆等變換公式,我們有

\[\sin(ax+b)=\sin(ax)\cos b+\cos(ax)\sin b \]

\(b\) 是給定的常數,所以

\[\sin(ax+b)=\cos b(ax-\frac{a^3x^3}{3!}+\frac{a^5x^5}{5!}-\frac{a^7x^7}{7!}+\cdots)+\sin b(1-\frac{a^2x^2}{2!}+\frac{a^4x^4}{4!}-\frac{a^6x^6}{6!}+\cdots) \]

\[\sin(ax+b)=\sum\limits_{i=0}^{\infty}\frac{\cos b(-1)^ia^{2i+1}x^{2i+1}}{(2i+1)!}+\frac{\sin b(-1)^ia^{2i}x^{2i}}{(2i)!} \]

然后維護一下這些 \(\texttt{EGF}\) 就可以直接做了。我的代碼維護到 \(15\) 項,所以比較慢,但還是能過。(至少不用像鰰一樣預處理組合數)

代碼

#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
typedef long double db;
const ll MAXN=2e5+51;
struct Polynomial{
    db cof[16];
    Polynomial()
    {
        memset(cof,0,sizeof(cof));
    }
    inline Polynomial operator +(const Polynomial &rhs)const
    {
        Polynomial res;
        for(register int i=0;i<16;i++)
        {
            res.cof[i]=cof[i]+rhs.cof[i];
        }
        return res;
    }
    inline db eval(db x)
    {
        db res=0,cur=1;
        for(register int i=0;i<16;i++)
        {
            res+=cof[i]*cur,cur*=x;
        }
        return res;
    }
    inline void op()
    {
        for(register int i=0;i<16;i++)
        {
            printf("%.8Lf\n",cof[i]);
        }
    }
};
ll n,m,x,y,typ;
db u,v;
string type,op;
inline ll read()
{
    register ll num=0,neg=1;
    register char ch=getchar();
    while(!isdigit(ch)&&ch!='-')
    {
        ch=getchar();
    }
    if(ch=='-')
    {
        neg=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        num=(num<<3)+(num<<1)+(ch-'0');
        ch=getchar();
    }
    return num*neg;
}
namespace LCT{
    struct Node{
        ll fa,rv,sz;
        Polynomial poly,sum;
        ll ch[2];
    };
    struct LinkCutTree{
        Node nd[MAXN];
        ll st[MAXN];
        #define ls nd[x].ch[0]
        #define rs nd[x].ch[1]
        inline bool nroot(ll x)
        {
            return nd[nd[x].fa].ch[0]==x||nd[nd[x].fa].ch[1]==x;
        }
        inline void update(ll x)
        {
            nd[x].sum=nd[ls].sum+nd[rs].sum+nd[x].poly;
        }
        inline void reverse(ll x)
        {
            swap(ls,rs),nd[x].rv^=1;
        }
        inline void spread(ll x)
        {
            if(nd[x].rv)
            {
                ls?reverse(ls):(void)(1),rs?reverse(rs):(void)(1);
                nd[x].rv=0;
            }
        }
        inline void rotate(ll x)
        {
            ll fa=nd[x].fa,gfa=nd[fa].fa;
            ll dir=nd[fa].ch[1]==x,son=nd[x].ch[!dir];
            if(nroot(fa))
            {
                nd[gfa].ch[nd[gfa].ch[1]==fa]=x;
            }
            nd[x].ch[!dir]=fa,nd[fa].ch[dir]=son;
            if(son)
            {
                nd[son].fa=fa;
            }
            nd[fa].fa=x,nd[x].fa=gfa,update(fa);
        }
        inline void splay(ll x)
        {
            ll fa=x,gfa,cur=0;
            st[++cur]=fa;
            while(nroot(fa))
            {
                st[++cur]=fa=nd[fa].fa;
            }
            while(cur)
            {
                spread(st[cur--]);
            }
            while(nroot(x))
            {
                fa=nd[x].fa,gfa=nd[fa].fa;
                if(nroot(fa))
                {
                    rotate((nd[fa].ch[0]==x)^(nd[gfa].ch[0]==fa)?x:fa);
                }
                rotate(x);
            }
            update(x);
        }
        inline void access(ll x)
        {
            for(register int i=0;x;x=nd[i=x].fa)
            {
                splay(x),rs=i,update(x);
            }
        }
        inline void makeRoot(ll x)
        {
            access(x),splay(x),reverse(x);
        }
        inline ll findRoot(ll x)
        {
            access(x),splay(x);
            while(ls)
            {
                spread(x),x=ls;
            }
            return x;
        }
        inline void split(ll x,ll y)
        {
            makeRoot(x),access(y),splay(y);
        }
        inline void link(ll x,ll y)
        {
            makeRoot(x);
            if(findRoot(y)!=x)
            {
                nd[x].fa=y;
            }
        }
        inline void cut(ll x,ll y)
        {
            makeRoot(x);
            if(findRoot(y)==x&&nd[x].fa==y&&!rs)
            {
                nd[x].fa=nd[y].ch[0]=0,update(y);
            }
        }
        #undef ls
        #undef rs
    };
}
LCT::LinkCutTree lct;
inline Polynomial sin(db u,db v)
{
    Polynomial res;
    db sinv=sin(v),cosv=cos(v),pw=1,fact=1;
    for(register int i=0;i<16;i++)
    {
        res.cof[i]=(i&2?-1:1)*(i&1?cosv:sinv)*pw*fact,pw*=u,fact/=(1.0*(i+1));
    }
    return res;
}
inline Polynomial exp(db u,db v)
{
    Polynomial res;
    db expv=exp(v),pw=1,fact=1;
    for(register int i=0;i<16;i++)
    {
        res.cof[i]=expv*pw*fact,pw*=u,fact/=1.0*(i+1);
    }
    return res;
}
inline Polynomial linear(db u,db v)
{
    Polynomial res;
    res.cof[0]=v,res.cof[1]=u;
    return res;
}
int main()
{
    n=read(),m=read(),cin>>type;
    for(register int i=1;i<=n;i++)
    {
        typ=read(),scanf("%Lf%Lf",&u,&v);
        lct.nd[i].poly=typ==1?sin(u,v):typ==2?exp(u,v):linear(u,v);
    }
    for(register int i=0;i<m;i++)
    {
        cin>>op;
        if(op=="appear")
        {
            x=read()+1,y=read()+1,lct.link(x,y);
        }
        if(op=="disappear")
        {
            x=read()+1,y=read()+1,lct.cut(x,y);
        }
        if(op=="magic")
        {
            x=read()+1,typ=read(),scanf("%Lf%Lf",&u,&v);
            lct.splay(x);
            lct.nd[x].poly=typ==1?sin(u,v):typ==2?exp(u,v):linear(u,v);
        }
        if(op=="travel")
        {
            x=read()+1,y=read()+1,scanf("%Lf",&u);
            if(lct.findRoot(x)!=lct.findRoot(y))
            {
                puts("unreachable");
                continue;
            }
            lct.split(x,y),printf("%.12Lf\n",lct.nd[y].sum.eval(u));
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM