卧薪尝胆,厚积薄发。
THUWC2017 在美妙的数学王国中畅游
Date: Thu Nov 22 13:26:20 CST 2018 In Category: NoCategory

Description:

给一个森林,每个点都有一个函数,可能是 $\sin(ax+b),e^{ax+b},ax+b$ 三个之一,有一个人带着一个值 $x$ ,从一个点沿着唯一的路径走到另一个点,经过这个点的时候会获得这个函数这么多分,多次询问得分之和。
$1\leqslant n\leqslant 100000$

Solution:

首先如果所有函数都是多项式的话那么我们就可以用 $LCT$ 维护多项式系数和但是本题不是多项式。
首先要知道泰勒展开公式: $$ f(x)\approx\sum_{i=0}^n\frac{f^{(i)}(x_0)}{i!}\times(x-x_0)^i $$ 当定义域包含 $0$ 时,有: $$ f(x)\approx\sum_{i=0}^n\frac{f^{(i)}(0)}{i!}\times x^i $$
还要知道几个函数的导数: $$ \begin{align} \sin(x)'&=\cos(x)\\ \cos(x)'&=-\sin(x)\\ \end{align} $$ 即: $$ \begin{align} \sin(x)^{(1)}&=\cos(x)\\ \sin(x)^{(2)}&=-\sin(x)\\ \sin(x)^{(3)}&=-\cos(x)\\ \sin(x)^{(4)}&=\sin(x) \end{align} $$ 然后就是循环了。 $$ (e^x)'=e^x $$
复合函数: $$ [f(g(x))]'=g'(x)\times f'(g(x)) $$ 于是有: $$ \begin{align} \sin(ax+b)^{(4n+0)}&=a^{4n+0}\sin(b)\\ \sin(ax+b)^{(4n+1)}&=a^{4n+1}\cos(b)\\ \sin(ax+b)^{(4n+2)}&=-a^{4n+2}\sin(b)\\ \sin(ax+b)^{(4n+3)}&=-a^{4n+3}\cos(b)\\ (e^{ax+b})^{n}&=a^ne^{ax+b}\\ \end{align} $$ 这样就把这些复杂的函数展开成了多项式的形式,只要用 $LCT$ 维护多项式系数和就行了。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<stack>
#include<cctype>
#include<cstring>
using namespace std;
int n,m;
#define MAXN 100010
struct poly
{
double f[12];
poly(){memset(f,0,sizeof(f));}
double calc(double x)
{
double cur = 1,ans = 0;
for(int i = 0;i < 12;++i,cur *= x)
{
ans += f[i] * cur;
}
return ans;
}
};
poly build(int f,double a,double b)
{
poly res;
if(f == 1)
{
double val = 1,fac = 1;
for(int i = 0;i < 3;++i)
{
double Sin = sin(b),Cos = cos(b);
res.f[4 * i + 0] += val * Sin;val *= a;
res.f[4 * i + 0] /= fac;fac *= 4 * i + 1;
res.f[4 * i + 1] += val * Cos;val *= a;
res.f[4 * i + 1] /= fac;fac *= 4 * i + 2;
res.f[4 * i + 2] -= val * Sin;val *= a;
res.f[4 * i + 2] /= fac;fac *= 4 * i + 3;
res.f[4 * i + 3] -= val * Cos;val *= a;
res.f[4 * i + 3] /= fac;fac *= 4 * i + 4;
}
}
if(f == 2)
{
double val = 1,e = exp(b),fac = 1;
for(int i = 0;i < 12;++i)
{
res.f[i] = val * e / fac;
val *= a;
fac *= i + 1;
}
}
if(f == 3)
{
res.f[0] = b;res.f[1] = a;
}
return res;
}
struct node
{
int c[2],fa;
poly s,sum;
bool rev;
node(){c[0] = c[1] = fa = 0;}
}t[MAXN];
void maintain(int k)
{
for(int i = 0;i < 12;++i)t[k].sum.f[i] = t[k].s.f[i];
if(t[k].c[0] != 0)for(int i = 0;i < 12;++i)t[k].sum.f[i] += t[t[k].c[0]].sum.f[i];
if(t[k].c[1] != 0)for(int i = 0;i < 12;++i)t[k].sum.f[i] += t[t[k].c[1]].sum.f[i];
return;
}
bool isroot(int k){return (t[t[k].fa].c[0] != k && t[t[k].fa].c[1] != k);}
int id(int k){return (t[t[k].fa].c[0] == k ? 0 : 1);}
void connect(int k,int f,int p){t[k].fa = f;t[f].c[p] = k;return;}
void pushdown(int k)
{
if(t[k].rev)
{
t[t[k].c[0]].rev ^= 1;t[t[k].c[1]].rev ^= 1;
swap(t[k].c[0],t[k].c[1]);t[k].rev = false;
}
return;
}
void rotate(int x)
{
int y = t[x].fa,z = t[y].fa,fx = id(x),fy = id(y);
if(!isroot(y))t[z].c[fy] = x;
t[x].fa = z;
connect(t[x].c[fx ^ 1],y,fx);
connect(y,x,fx ^ 1);
maintain(y);maintain(x);
return;
}
stack<int> s;
void splay(int x)
{
s.push(x);
for(int i = x;!isroot(i);i = t[i].fa)s.push(t[i].fa);
while(!s.empty()){pushdown(s.top());s.pop();}
while(!isroot(x))
{
int y = t[x].fa;
if(isroot(y)){rotate(x);break;}
if(id(x) == id(y)){rotate(y);rotate(x);}
else{rotate(x);rotate(x);}
}
return;
}
void access(int k){for(int i = 0;k;i = k,k = t[k].fa){splay(k);t[k].c[1] = i;maintain(k);}return;}
void makeroot(int k){access(k);splay(k);t[k].rev ^= 1;return;}
void split(int x,int y){makeroot(x);access(y);splay(y);return;}
void link(int x,int y){makeroot(x);t[x].fa = y;return;}
void cut(int x,int y){split(x,y);t[x].fa = t[y].c[0] = 0;maintain(y);return;}
int findroot(int k){access(k);splay(k);while(t[k].c[0] != 0)k = t[k].c[0];return k;}
int main()
{
char c[20];
scanf("%d%d%s",&n,&m,c);
int f;double a,b;
for(int i = 1;i <= n;++i)
{
scanf("%d%lf%lf",&f,&a,&b);
t[i].s = build(f,a,b);
}
int x,y;
for(int i = 1;i <= m;++i)
{
scanf("%s",c);
if(c[0] == 'a')
{
scanf("%d%d",&x,&y);
++x;++y;
link(x,y);
}
if(c[0] == 'd')
{
scanf("%d%d",&x,&y);
++x;++y;
cut(x,y);
}
if(c[0] == 'm')
{
scanf("%d",&x);
++x;
splay(x);
scanf("%d%lf%lf",&f,&a,&b);
t[x].s = build(f,a,b);
maintain(x);
}
if(c[0] == 't')
{
scanf("%d%d",&x,&y);
scanf("%lf",&a);
++x;++y;
if(findroot(x) != findroot(y))
{
puts("unreachable");
continue;
}
split(x,y);
printf("%.10lf\n",t[y].sum.calc(a));
}
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡