1. 程式人生 > >[THUWC 2017]在美妙的數學王國中暢遊

[THUWC 2017]在美妙的數學王國中暢遊

lin mes cut rotate algo reverse queue 數學 style

https://loj.ac/problem/2289

LCT+泰勒展開

首先e^x求導完是ln e * e^x還是e^x

sin x求導完變成cos x,cos x求導完變成sin x

由於復合函數f(g(x))求導完是f‘(g(x))*g‘(x)

所以就可以輕松的推出sin x和e^x的n階導數

對於泰勒展開的那個公式,我們發現x0=0.5時,每一項的系數為1/2/n!,到了後面對ans的影響非常小,可以忽略,於是我們只要把多項式的前14項提出來就好。

接下來動態樹上的操作用Link Cut Tree維護一下就ok了

code :

#include <iostream>
#include <cstdio>
#include 
<cstring> #include <algorithm> #include <cstdlib> #include <cassert> #include <cmath> #include <complex> #include <bitset> #include <vector> #include <queue> #include <stack> #include <set> #include <map> #define rep(i, a, b) for(int (i) = (a), __omega = (b); (i) <= __omega; ++(i)) #define
down(i, a, b) for(int (i) = (a), __omega = (b); (i) >= (b); --(i)) #define openfile(name) freopen(name".in", "r", stdin), freopen(name".out", "w", stdout) using namespace std; const double x0 = 0.5; const int bit = 14; double frac[20]; void init_frac() { frac[0] = 1; for(int i = 1; i <= bit; ++i) frac[i] = frac[i-1
]*i; } //預處理階乘 //sin(x)的n階導 double diff_sin(int n, double x) { double k = ((n&3) == 0 || (n&3) == 1) ? 1 : -1; if(n&1) return k*cos(x); else return k*sin(x); } struct poly { double a[20]; friend poly operator+(poly a, poly b) { for(int i = bit; ~i; --i) a.a[i] += b.a[i]; return a; } double operator()(double x) { x -= x0; double res = 0; for(int i = bit; ~i; --i) res *= x, res += a[i]; return res; } void get_line(double A, double B) { memset(a, 0, sizeof(double)*20); a[0] = B+x0*A; a[1] = A; } void get_sin(double A, double B) { memset(a, 0, sizeof(double)*20); double xx = A*x0+B; double an = 1; for(int i = 0; i <= bit; ++i) { a[i] = an*diff_sin(i, xx)/frac[i]; an = an*A; } } void get_exp(double A, double B) { memset(a, 0, sizeof(double)*20); double xx = A*x0+B; double an = 1; for(int i = 0; i <= bit; ++i) { a[i] = an*exp(xx)/frac[i]; an = an*A; } } }; struct node *nul; struct node { node *son[2], *top, *fa; poly val, sum; int rev; void reverse() { rev ^= 1; swap(son[0], son[1]); } void push_up() { sum = val+(son[0]->sum)+(son[1]->sum); } void push_down() { if(rev) { rev ^= 1; son[0]->reverse(); son[1]->reverse(); } } int pos() { return fa->son[1] == this; } void rotate() { int d = pos(); node *y = fa; y->push_down(); push_down(); top = y->top; if(y->fa != nul) y->fa->son[y->pos()] = this; y->son[d] = son[d^1], son[d^1] = y; if(y->son[d] != nul) y->son[d]->fa = y; fa = y->fa, y->fa = this; y->push_up(), push_up(); } void splay() { push_down(); for(node *y = fa; fa != nul; rotate()) if(y = fa, y->fa != nul) y->pos()^pos() ? rotate() : y->rotate(); push_up(); } void expose(node *p = nul) { splay(); if(son[1] != nul) { son[1]->fa = nul; son[1]->top = this; } son[1] = p; if(p != nul) p->fa = this; push_up(); } } pos[100010]; node *access(node *x) { for(x->expose(); x->top; x = x->top) x->top->expose(x); return x; } void link(node *x, node *y) { x = access(x); x->reverse(); x->top = y; } void cut(node *x, node *y) { x->expose(), y->expose(); if(x->top == y) x->top = 0; if(y->top == x) y->top = 0; } node *root(node *x) { x = access(x); for(; x->son[0] != nul; x = x->son[0]); return x; } int n, m; poly p[100010]; char spe[5]; int main() { init_frac(); scanf("%d%d%s", &n, &m, spe); nul = pos; for(int i = 0; i <= n; ++i) { (pos+i)->fa = (pos+i)->son[0] = (pos+i)->son[1] = nul; } for(int i = 1; i <= n; ++i) { int type; double a, b; scanf("%d%lf%lf", &type, &a, &b); if(type == 1) { p[i].get_sin(a, b); } else if(type == 2) { p[i].get_exp(a, b); } else if(type == 3) { p[i].get_line(a, b); } (pos+i)->val = (pos+i)->sum = p[i]; } while(m--) { static char str[20]; scanf("%s", str); if(!strcmp(str, "appear")) { int u, v; scanf("%d%d", &u, &v); u++, v++; link(pos+u, pos+v); } else if(!strcmp(str, "disappear")) { int u, v; scanf("%d%d", &u, &v); u++, v++; cut(pos+u, pos+v); } else if(!strcmp(str, "magic")) { int c, f; double a, b; scanf("%d%d%lf%lf", &c, &f, &a, &b); c++; if(f == 1) { p[c].get_sin(a, b); } else if(f == 2) { p[c].get_exp(a, b); } else if(f == 3) { p[c].get_line(a, b); } access(pos+c); (pos+c)->sum = (pos+c)->val = p[c]; } else if(!strcmp(str, "travel")) { int u, v; double x; scanf("%d%d%lf", &u, &v, &x); u++, v++; if(root(pos+u) != root(pos+v)) { puts("unreachable"); } else { access(pos+u); (pos+u)->splay(); (pos+u)->reverse(); poly f = access(pos+v)->sum; printf("%.9lf\n", f(x)); } } else { puts("orz fjzzq2002!"); } } return 0; }

[THUWC 2017]在美妙的數學王國中暢遊