@description@

n 个点编号 0 到 n-1,每个点有一个从 [0,1] 映射到 [0,1] 的函数 f(x) 作为点权,它有以下几种形式:

正弦函数:sin(ax+b) (a∈[0,1],b∈[0,π],a+b∈[0,π])

指数函数:e^(ax+b) (a∈[−1,1],b∈[−2,0],a+b∈[−2,0])

一次函数:ax+b (a∈[−1,1],b∈[0,1],a+b∈[0,1])

有 m 个事件,种类如下:

(1)加边。

(2)删边。

(3)更改点权。

(4)询问 u 到 v 这条路径上的所有函数以 x(给定)为自变量的因变量之和。

保证一开始不存在任何边。

input

第一行两个正整数 n,m 和一个字符串 type。表示 n 个点与 m 个事件,type 是用来得部分分的。1≤n≤100000,1≤m≤200000 。

接下来 n 行,第 i 行表示编号为 i 的点的初始函数。一个整数 f 表示函数的类型,两个实数 a,b 表示函数的参数:

f=1 ,则函数为 f(x)=sin(ax+b)(a∈[0,1],b∈[0,π],a+b∈[0,π])

f=2 ,则函数为 f(x)=e^(ax+b) (a∈[−1,1],b∈[−2,0],a+b∈[−2,0])

f=3 ,则函数为 f(x)=ax+b(a∈[−1,1],b∈[0,1],a+b∈[0,1])

接下来 m 行,每行描述一个事件,事件分为四类:

appear u v:表示数学王国中出现了一条连接 u 和 v 这两座城市的魔法桥 (0≤u,v<n,u ≠ v) ,保证连接前 u 和 v 这两座城市不能互相到达。

disappear u v: 表示数学王国中连接 u 和 v 这两座城市的魔法桥消失了,保证这座魔法桥是存在的。

magic c f a b:表示城市 c 的魔法球中的魔法变成了类型为 f ,参数为 a,b 的函数

travel u v x:表示询问一个智商为 x 的人从城市 u 旅行到城市 v (即经过 u 到 v 这条路径上的所有城市,包括 u 和 v )后,他得分的总和是多少。若无法从 u 到达 v ,则输出一行一个字符串 unreachable。

output

对于每个询问,输出一行实数,表示答案。建议使用科学计数法表示。

sample input

3 7 C1

1 1 0

3 0.5 0.5

3 -0.5 0.7

appear 0 1

travel 0 1 0.3

appear 0 2

travel 1 2 0.5

disappear 0 1

appear 1 2

travel 1 2 0.5

sample output

9.45520207e-001

1.67942554e+000

1.20000000e+000

hint

【出题人教你学数学】

若函数 \(f(x)\) 的 \(n\) 阶导数在 \([a,b]\) 区间内连续,则对 \(f(x)\) 在 \(x_0(x_0\in[a,b])\) 处使用 n 次拉格朗日中值定理可以得到带拉格朗日余项的泰勒展开式:

\[f(x)=f(x_0)+\frac{f'(x_0)(x-x_0)}{1!}+\frac{f''(x_0)(x-x_0)^2}{2!}+ \cdots +\frac{f^{(n-1)}(x_0)(x-x_0)^{n-1}}{(n-1)!}+\frac{f^{(n)}(\xi)(x-x_0)^n}{n!},x\in[a,b]
\]

其中,当 \(x>x_0\) 时,\(\xi\in[x_0,x]\)。当 \(x<x_0\) 时,\(\xi\in[x,x_0]\)。

\(f^{(n)}\) 表示函数 \(f\) 的 \(n\) 阶导数

@solution@

都加边删边了,那肯定是用 LCT 来维护了。

一次函数还好说,直接链上维护一次项系数与常数系数之和(但是竟然没有这部分的部分分?)。

考虑指数函数或是三角函数的和,这个东西是没有任何实际的意义的,无法用什么统一的数据表示。

但是题目中给的泰勒展开这玩意儿,其意义就是用多项式函数去逼近这些非多项式的函数。

那我们为什么不直接用泰勒展开来逼近就可以了?取前二十项的,误差就足够小了。

而多项式就可以直接用一次函数的方法,维护每一项的系数之和。

那么怎么求导呢?显然我一个初中生是做不来的。

直接摆公式吧:

指数函数:\(f(x) = e^x, f'(x) = e^x\)。

三角函数 sin:\(f(x) = sin(x), f'(x) = cos(x)\)。三角函数 cos:\(f(x) = cos(x), f'(x) = -sin(x)\)。

幂函数: \(f(x) = x^a, f'(x) = ax^{a-1}\)。常函数:\(f(x) = k, f'(x) = 0\)。

函数和的导数:\(h(x) = f(x) + g(x), h'(x) = f'(x) + g'(x)\)。

函数积的导数:\(h(x) = f(x)*g(x), h'(x) = f(x)*g'(x) + f'(x)*g(x)\)。

复合函数的导数:\(h(x) = f(g(x)), h'(x) = f'(g(x))*g'(x)\)。

那么对于函数 \(f(x) = e^{ax+b}\),它的 n 阶导数为 \(f^{(n)}=a^ne^{ax+b}\)。

对于函数 \(f(x) = sin(x)\),它的 n 阶导数的系数绝对值为 \(a^n\),剩下的以四为循环节:\(sin(x)\),\(cos(x)\),\(-sin(x)\),\(-cos(x)\)。

对于函数 \(f(x) = ax + b\),这个就不讲了。

@accepted code@

#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef double db;
const int MAXN = 100000;
struct node{
int rev;
node *ch[2], *fa;
db k[20], s[20];
}pl[MAXN + 5], *ad[MAXN + 5], *NIL;
bool isroot(node *x) {return x->fa->ch[0] != x && x->fa->ch[1] != x;}
void setchild(node *x, node *y, int d) {
if( x != NIL ) x->ch[d] = y;
if( y != NIL ) y->fa = x;
}
void pushup(node *x) {
for(int i=0;i<20;i++)
x->s[i] = x->ch[0]->s[i] + x->ch[1]->s[i] + x->k[i];
}
void pushdown(node *x) {
if( x->rev ) {
swap(x->ch[0], x->ch[1]);
if( x->ch[0] != NIL ) x->ch[0]->rev ^= 1;
if( x->ch[1] != NIL ) x->ch[1]->rev ^= 1;
x->rev = 0;
}
}
void rotate(node *x) {
node *y = x->fa; pushdown(y), pushdown(x);
int d = (y->ch[1] == x);
if( isroot(y) ) x->fa = y->fa;
else setchild(y->fa, x, (y->fa->ch[1] == y));
setchild(y, x->ch[!d], d);
setchild(x, y, !d);
pushup(y);
}
void splay(node *x) {
pushdown(x);
while( !isroot(x) ) {
node *y = x->fa;
if( isroot(y) )
rotate(x);
else {
if( (y->fa->ch[1] == y) == (y->ch[1] == x) )
rotate(y);
else rotate(x);
rotate(x);
}
}
pushup(x);
}
void access(node *x) {
node *y = NIL;
while( x != NIL ) {
splay(x);
x->ch[1] = y;
pushup(x);
y = x, x = x->fa;
}
}
void makeroot(node *x) {
access(x);splay(x);
x->rev ^= 1;
}
node *findroot(node *x) {
access(x), splay(x);
node *ret = x;
while( ret->ch[0] != NIL ) ret = ret->ch[0];
return ret;
}
void link(node *x, node *y) {
makeroot(x); x->fa = y;
}
void cut(node *x, node *y) {
makeroot(x); access(y), splay(y);
y->ch[0] = NIL; x->fa = NIL;
pushup(y);
}
void modify(db k[], int f, db a, db b) {
if( f == 1 ) {
db m = 1, x = sin(b), y = cos(b);
for(int i=0;i<20;i+=4) {
k[i + 0] = x*m, m = m*a/(i+1);
k[i + 1] = y*m, m = m*a/(i+2);
k[i + 2] = -x*m, m = m*a/(i+3);
k[i + 3] = -y*m, m = m*a/(i+4);
}
}
else if( f == 2 ) {
db m = 1, x = exp(b);
for(int i=0;i<20;i++)
k[i] = x*m, m = m*a/(i+1);
}
else if( f == 3 ) {
for(int i=0;i<20;i++)
k[i] = 0;
k[0] = b, k[1] = a;
}
}
db calculate(db k[], db x) {
db ret = 0, p = 1;
for(int i=0;i<20;i++)
ret += p*k[i], p *= x;
return ret;
}
void init() {NIL = &pl[0], NIL->ch[0] = NIL->ch[1] = NIL->fa = NIL;}
char op[10];
int main() {
int n, m; init();
scanf("%d%d%s", &n, &m, op);
for(int i=1;i<=n;i++) {
ad[i] = &pl[i], ad[i]->ch[0] = ad[i]->ch[1] = ad[i]->fa = NIL;
for(int j=0;j<20;j++)
ad[i]->k[j] = ad[i]->s[j] = 0;
int f; db a, b; scanf("%d%lf%lf", &f, &a, &b);
modify(ad[i]->k, f, a, b), pushup(ad[i]);
}
for(int i=1;i<=m;i++) {
scanf("%s", op);
if( op[0] == 'a' ) {
int u, v; scanf("%d%d", &u, &v); u++, v++;
link(ad[u], ad[v]);
}
if( op[0] == 'd' ) {
int u, v; scanf("%d%d", &u, &v); u++, v++;
cut(ad[u], ad[v]);
}
if( op[0] == 'm' ) {
int c, f; db a, b; scanf("%d%d%lf%lf", &c, &f, &a, &b); c++;
access(ad[c]), splay(ad[c]), modify(ad[c]->k, f, a, b), pushup(ad[c]);
}
if( op[0] == 't' ) {
int u, v; db x; scanf("%d%d%lf", &u, &v, &x); u++, v++;
makeroot(ad[u]);
if( findroot(ad[v]) != ad[u] ) puts("unreachable");
else {
db ans = calculate(ad[v]->s, x); int k = 0;
if( ans < 1 ) {
while( ans < 1 ) ans *= 10, k++;
printf("%0.8lfe-%03d\n", ans, k);
}
else {
while( ans >= 10 ) ans /= 10, k++;
printf("%0.8lfe+%03d\n", ans, k);
}
}
}
}
}

@details@

想到我考前还没写过 LCT。

想到我还要这道题没做。

于是就有了这篇博客。

另外,虽然题目是建议科学计数法,但是如果不用科学计数法就会因为浮点误差 WA 掉。

原因?你想啊,假如一个五位数从 10^(-6) 开始出现误差,你把它变成科学计数法,它在 10^(-7) 之前不就都没有误差了吗?

@loj - 2289@「THUWC 2017」在美妙的数学王国中畅游的更多相关文章

  1. 【LOJ】#2289. 「THUWC 2017」在美妙的数学王国中畅游

    题解 我们发现,题目告诉我们这个东西就是一个lct 首先,如果只有3,问题就非常简单了,我们算出所有a的总和,所有b的总和就好了 要是1和2也是多项式就好了--其实可以!也就是下面泰勒展开的用处,我们 ...

  2. 「LOJ 2289」「THUWC 2017」在美妙的数学王国中畅游——LCT&泰勒展开

    题目大意: 传送门 给一个动态树,每个节点上维护一个函数为$f(x)=sin(ax+b)$.$f(x)=e^{ax+b}$.$f(x)=ax+b$中的一个. 支持删边连边,修改节点上函数的操作. 每次 ...

  3. 「THUWC 2017」在美妙的数学王国中畅游

    这个题目很明显在暗示你要用泰勒展开. 直接套上去泰勒展开的式子,精度的话保留12项左右即可. 分别维护每一项的和,可能比较难写吧. 然后强行套一个LCT就没了.

  4. 【THUWC 2017】在美妙的数学王国中畅游

    数学王国里有n座城市,每座城市有三个参数\(f\),\(a\),\(b\),一个智商为\(x\)的人经过一座城市的获益\(f(x)\)是 若\(f=1\),则\(f(x)=\sin(ax+b)\): ...

  5. LOJ 2288「THUWC 2017」大葱的神力

    LOJ 2288「THUWC 2017」大葱的神力 Link Solution 比较水的提交答案题了吧 第一个点爆搜 第二个点爆搜+剪枝,我的剪枝就是先算出 \(mx[i]\) 表示选取第 \(i \ ...

  6. 【BZOJ5020】[THUWC 2017]在美妙的数学王国中畅游 泰勒展开+LCT

    [BZOJ5020][THUWC 2017]在美妙的数学王国中畅游 Description 数字和数学规律主宰着这个世界. 机器的运转, 生命的消长, 宇宙的进程, 这些神秘而又美妙的过程无不可以用数 ...

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

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

  8. 【BZOJ5020】【THUWC2017】在美妙的数学王国中畅游(Link-Cut Tree,组合数学)

    [BZOJ5020][THUWC2017]在美妙的数学王国中畅游(Link-Cut Tree,组合数学) 题解 Description 数字和数学规律主宰着这个世界. 机器的运转, 生命的消长, 宇宙 ...

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

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

随机推荐

  1. Eclipse luna安装 Ivy

    在线安装地址:http://www.apache.org/dist/ant/ivyde/updatesite

  2. mysql查询某个字段重复的数据

    查询某个字段重复的数据 ; 查询股票重复的营业厅 ;

  3. netbeans生成的maven工程没有web.xml文件 如何新建

    使用netbeans生成的maven工程没有web.xml 需要自己新建 步骤: 下一步,完成

  4. 推荐大家自学的java学习网站,生动的讲解适合刚入门

    java学习网站(不仅仅是只学习java的知识):http://how2j.cn 首先大家来看看这个网站都有些啥 首页:图中的左侧目录大家看到了,从java基础到高级,从后台技术到前端页面,数据库,还 ...

  5. 破逼Json,该死的Json库,操了

    jansson,就这个库,破几把玩意,本来很简单的Json,就是简单的字符串操作,ATL一个CString就能解决,QT的QSting也能解决,DELPHI的String也能解决.而这B,非把那么简单 ...

  6. 001. 注释过的boot.s

    从网上搜罗一个很详细注释的boot.s版本,加了小小一点点自己的理解,不太多. 用 as86, ld86 可以编译,   ubuntu下可以通过 apt install bin86 来安装好像. ; ...

  7. 从零起步 系统入门Python爬虫工程师

    从零起步 系统入门Python爬虫工程师 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身没问题,大家看的 ...

  8. C++ 之手写strcpy

    char *strcpy(char* strDest, const char*strSrc){ assert(strDest != NULL&&strSrc != NULL); cha ...

  9. CentOS上搭建Yii2 --2017

    1.安装composer(作曲家?好像是php的包管理,类似python中的pip) #安装 curl -sS https://getcomposer.org/installer | php #移动到 ...

  10. MSSQL 为db创建user

    use [IBatisNet]GO if not exists (select * from master.dbo.syslogins where loginname = N'IBatisNet')B ...