题意

题意奇奇怪怪,这里就不写了。

\(\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));
}
}
}

Luogu P4546 [THUWC2017]在美妙的数学王国中畅游的更多相关文章

  1. 洛谷P4546 [THUWC2017]在美妙的数学王国中畅游 [LCT,泰勒展开]

    传送门 毒瘤出题人卡精度-- 思路 看到森林里加边删边,容易想到LCT. 然而LCT上似乎很难实现往一条链里代一个数进去求和,怎么办呢? 善良的出题人在下方给了提示:把奇怪的函数泰勒展开搞成多项式,就 ...

  2. P4546 [THUWC2017]在美妙的数学王国中畅游

    如果只有第3个操作,那么这就是个sd题,随便lct搞搞就过去了 然后就是一个神仙东西 taylor公式 我不会,看gsy博客https://www.cnblogs.com/zhoushuyu/p/81 ...

  3. 并不对劲的bzoj5020:loj2289:p4546:[THUWC2017]在美妙的数学王国中畅游

    题目大意 有一个n(\(n\leq 10^5\))个点的森林,每个点\(u\)上有个函数\(f_u(x)\),是形如\(ax+b\)或\(e^{ax+b}\)或\(sin(ax+b)\)的函数,保证当 ...

  4. [THUWC2017]在美妙的数学王国中畅游

    [THUWC2017]在美妙的数学王国中畅游 e和sin信息不能直接合并 泰勒展开,大于21次太小,认为是0,保留前21次多项式即可 然后就把e,sin ,kx+b都变成多项式了,pushup合并 上 ...

  5. [BZOJ5020][THUWC2017]在美妙的数学王国中畅游(LCT)

    5020: [THUWC 2017]在美妙的数学王国中畅游 Time Limit: 80 Sec  Memory Limit: 512 MBSec  Special JudgeSubmit: 323  ...

  6. 题解 洛谷 P4546 【[THUWC2017]在美妙的数学王国中畅游】

    首先发现有连边和删边的操作,所以我们肯定要用\(LCT\)来进行维护. 接下来考虑如何进行\(LCT\)上的信息合并. \(f=1\),则函数为\(f(x)=sin(ax+b)\) \(f=2\),则 ...

  7. Luogu4546 THUWC2017 在美妙的数学王国中畅游 LCT、泰勒展开

    传送门 题意:反正就是一堆操作 LCT总是和玄学东西放在一起我们不妨令$x_0=0.5$(其实取什么都是一样的,但是最好取在$[0,1]$的范围内),将其代入给出的式子,我们得到的$f(x)$的式子就 ...

  8. BZOJ5020 THUWC2017在美妙的数学王国中畅游(LCT)

    明摆着的LCT,问题在于如何维护答案.首先注意到给出的泰勒展开式,并且所给函数求导非常方便,肯定要用上这玩意.容易想到展开好多次达到精度要求后忽略余项.因为x∈[0,1]而精度又与|x-x0|有关,当 ...

  9. [THUWC2017]在美妙的数学王国中畅游 LCT+泰勒展开+求导

    p.s. 复合函数求导时千万不能先带值,再求导. 一定要先将符合函数按照求导的规则展开,再带值. 设 $f(x)=g(h(x))$,则对 $f(x)$ 求导: $f'(x)=h'(x)g'(h(x)) ...

随机推荐

  1. OSPF及实验

    OSPF:Open Shortest Path First,最短路径优先1)基本概念:标准的LS型协议--共享拓扑组播更新:224.0.0.5/6触发更新,存在周期更新  30minOSPF是跨层封装 ...

  2. JMETER并发压测-自定义不同请求参数

    背景 虽然可以请求相同的接口做测试,但是请求参数每次都是相同的.为了模拟不同的用户,请求不同的参数,所以要自定义参数来做多线程并发压力测试. 点赞再看,关注公众号:[地藏思维]给大家分享互联网场景设计 ...

  3. NX二次开发-C#使用DllImport调用libufun.dll里的UF函数(反编译.net.dll)调用loop等UF函数

    在写这篇文章的时候,我正在头晕,因为下班坐车回家,有些晕车了.头疼的要死.也吃不下去饭. 版本:NX11+VS2013 最近这一年已经由C++过度到C#,改用C#做应用程序开发和NX二次开发. C#在 ...

  4. Java单播、组播(多播)、广播的简单实现

    简介 单播有TCP和UDP两种实现,组播(多播)和广播只有UDP一种实现.单播和广播基本一样,只是广播的数据包IP为广播IP.   单播 DatagramSocket和DatagramPacket 服 ...

  5. java安全编码指南之:输入注入injection

    目录 简介 SQL注入 java中的SQL注入 使用PreparedStatement XML中的SQL注入 XML注入的java代码 简介 注入问题是安全中一个非常常见的问题,今天我们来探讨一下ja ...

  6. thinkphp5 chunk 分块处理数据小坑

    场景: 使用chunk方法进行分块查询写入数据,执行发现chunk分几条一次处理 数据库就插入几条,并没有return false; 代码如下 解决方法: 增加排序字段

  7. 【手摸手,带你搭建前后端分离商城系统】01 搭建基本代码框架、生成一个基本API

    [手摸手,带你搭建前后端分离商城系统]01 搭建基本代码框架.生成一个基本API 通过本教程的学习,将带你从零搭建一个商城系统. 当然,这个商城涵盖了很多流行的知识点和技术核心 我可以学习到什么? S ...

  8. 多测师讲解selenium_输入性弹框定位_高级讲师肖sir

    #输入性弹框from selenium import webdriverfrom time import sleepdrvier=webdriver.Chrome()url='file:///F:\d ...

  9. JS学习之路一

    1.准备 ①安装vscode 地址:https://vscode.en.softonic.com/ ②安装node.js node -v npm -v 地址:https://nodejs.org/zh ...

  10. day61 Pyhton 框架Django 04

    内容回顾 1.django处理请求的流程: 1. 在浏览器的地址栏输入地址,回车发get请求: 2. wsgi模块接收请求: 3. 在urls.py文件中匹配地址,找到对应的函数: 4. 执行函数,返 ...