THUWC2017 T1

45 篇文章 0 订阅
2 篇文章 0 订阅

THUWC2017 T1


考场上的心路历程

因为当时还不会泰勒展开,拉格朗日余项,拉格朗日中值定理和导数(本来我预习了的,但是考试的时候不记得导数的符号了,导致没有看懂给出的提示),所以只好打了一个LCT维护联通性,打算骗分。

但是因为基本功不扎实,LCT并写不对。

回来之后深刻反省,苦练LCT,终于一个小时1A此题。


时间限制: 5.0 秒

内存限制: 512 MB

相关文件: 下载目录

【问题背景】

数字和数学规律主宰着这个世界。

机器的运转,

生命的消长,

宇宙的进程,

这些神秘而又美妙的过程无不可以用数学的语言展现出来。

这印证了一句古老的名言:

“学好数理化,走遍天下都不怕。”

【问题描述】

学渣小R被大学的数学课程虐得生活不能自理,微积分的成绩曾是他在教室里上的课的最低分。然而他的某位陈姓室友却能轻松地在数学考试中得到满分。为了提升自己的数学课成绩,有一天晚上(在他睡觉的时候),他来到了数学王国。

数学王国中,每个人的智商可以用一个属于 [0,1] 的实数表示。数学王国中有 n 个城市,编号从0 n1 ,这些城市由若干座魔法桥连接。每个城市的中心都有一个魔法球,每个魔法球中藏有一道数学题。每个人在做完这道数学题之后都会得到一个在 [0,1] 区间内的分数。一道题可以用一个从 [0,1] 映射到 [0,1] 的函数 f(x) 表示。若一个人的智商为 x ,则他做完这道数学题之后会得到f(x)分。函数 f 有三种形式:

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

    • 指数函数 eax+b (a[1,1],b[2,0],a+b[2,0])
    • 一次函数 ax+b (a[1,1],b[0,1],a+b[0,1])
    • 数学王国中的魔法桥会发生变化,有时会有一座魔法桥消失,有时会有一座魔法桥出现。但在任意时刻,只存在至多一条连接任意两个城市的简单路径(即所有城市形成一个森林)。在初始情况下,数学王国中不存在任何的魔法桥。

      数学王国的国王拉格朗日很乐意传授小R数学知识,但前提是小R要先回答国王的问题。这些问题具有相同的形式,即一个智商为 x 的人从城市u旅行到城市 v (即经过u v 这条路径上的所有城市,包括u v )且做了所有城市内的数学题后,他所有得分的总和是多少。

      【输入格式】

      从标准输入读入数据。

      第一行两个正整数 n,m和一个字符串 type 。表示数学王国中共有 n 座城市,发生了m个事件,该数据的类型为 type type 字符串是为了能让大家更方便地获得部分分,你可能不需要用到这个输入。其具体含义在【限制与约定】中有解释。

      接下来 n 行,第i行表示初始情况下编号为 i 的城市的魔法球中的函数。一个魔法用一个整数 f 表示函数的类型,两个实数 a,b 表示函数的参数,若

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

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

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

      2. disappear u v 表示数学王国中连接 u v这两座城市的魔法桥消失了,保证这座魔法桥是存在的。
      3. magic c f a b 表示城市 c 的魔法球中的魔法变成了类型为f,参数为 a,b 的函数
      4. travel u v x 表示询问一个智商为 x 的人从城市u旅行到城市 v (即经过u v 这条路径上的所有城市,包括u v )后,他得分的总和是多少。若无法从u到达 v ,则输出一行一个字符串 unreachable

      【输出格式】

      输出到标准输出。

      对于每个询问,输出一行实数,表示得分的总和。

      【样例1】

      输入

      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
      

      输出

      9.45520207e-001
      1.67942554e+000
      1.20000000e+000
      

      【限制与约定】

      对于100%的数据,1n100000,1m200000

      本题共有20个数据点,每个数据点5分。

      【评分标准】

      如果你的答案与标准答案的相对误差在 107 以内或绝对误差在 107 以内,则被判定为正确。

      如果你的所有答案均为正确,则得满分,否则得0分。

      请注意输出格式:每行输出一个答案,答案只能为 unreachable 或者一个实数(建议使用科学计数法表示)。每行的长度不得超过50。错误输出格式会被判定为0分。

      【小R教你学数学】

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

      f(x)=f(x0)+f(x0)(xx0)1!+f(x0)(xx0)22!++f(n1)(x0)(xx0)n1(n1)!+f(n)(ξ)(xx0)nn!,x[a,b]

      其中,当 x>x0 时, ξ[x0,x] 。当 x<x0 时, ξ[x,x0]

      f(n) 表示函数 f n阶导数


      Code

      #include <bits/stdc++.h>
      
      const int MAXS = 20;
      
      int n, m;
      char type[MAXS];
      
      int u, v, c, f;
      
      double x, a, b;
      
      template <typename Tp> void in(Tp &x) {
          char ch = getchar(); x = 0; char f = 1;
          while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
          if (ch == '-') f = -1, ch = getchar();
          while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
          x *= f;
      }
      
      namespace T
      {
          const int MAXN = 100010;
          const int MAXB = 30;
      
          int sz, fat[MAXN];
      
          struct Node {
              int num;
              bool isa;
              Node *fa, *ch[2];
              double data[MAXB + 1], sum[MAXB + 1];
      
              void pushdown();
              void update();
      
              void splay();
              void rotate();
              void access();
              void be_rot();
      
              bool is_rot();
              int find_rot();
          };
      
          Node *nul = new Node, *to[MAXN];
      
          bool Node::is_rot() {return fa == nul || fa -> ch[0] != this && fa -> ch[1] != this;}
      
          void Node::rotate()
          {
              Node *pa = fa; fa = pa -> fa;
              if (!pa -> is_rot()) {
                  bool t = (fa -> ch[0] == pa ? 0 : 1);
                  fa -> ch[t] = this;
              }
      
              bool t = (pa -> ch[0] == this ? 0 : 1);
              pa -> fa = this; pa -> ch[t] = ch[t^1];
              if (ch[t^1] != nul) ch[t^1] -> fa = pa;
              ch[t^1] = pa;
              pa -> update(); update();
          }
      
          void Node::access()
          {
              Node *x = this;
              x -> splay(); x -> pushdown();
              x -> ch[1] = nul; x -> update();
              while (x -> fa != nul) {
                  Node *e = x -> fa;
                  e -> splay(); e -> pushdown();
                  e -> ch[1] = x; e -> update();
                  x = e;
              }
          }
      
          void Node::splay()
          {
              sz = 0;
              Node *tmp = this;
              while (!tmp -> is_rot()) {
                  fat[++sz] = tmp -> num;
                  tmp = tmp -> fa;
              }
              fat[++sz] = tmp -> num;
              for (int i = sz; i >= 1; i--) to[fat[i]] -> pushdown();
      
              while (!is_rot()) {
                  if (fa -> is_rot()) rotate();
                  else {
                      bool t = (fa -> fa -> ch[0] == fa ? 0 : 1);
                      if (fa -> ch[t] == this) fa -> rotate(), rotate();
                      else rotate(), rotate();
                  }
              }
          }
      
          void Node::pushdown()
          {
              if (!isa) return;
              isa = false;
              Node *tmp = ch[0]; ch[0] = ch[1]; ch[1] = tmp;
              if (ch[0] != nul) ch[0] -> isa ^= 1;
              if (ch[1] != nul) ch[1] -> isa ^= 1;
          }
      
          int Node::find_rot()
          {
              access(); splay();
              Node *tmp = this;
              pushdown();
              while (tmp -> ch[0] != nul) {
                  tmp = tmp -> ch[0];
                  tmp -> pushdown();
              }
              return tmp -> num;
          }
      
          void Node::be_rot()
          {
              access(); splay();
              isa ^= 1;
          }
      
          void Node::update()
          {
              memset(sum, 0, sizeof sum);
              for (int i = 0; i <= MAXB; i++) sum[i] += data[i];
              if (ch[0] != nul)
                  for (int i = 0; i <= MAXB; i++) sum[i] += ch[0] -> sum[i];
              if (ch[1] != nul)
                  for (int i = 0; i <= MAXB; i++) sum[i] += ch[1] -> sum[i];
          }
      
          void main()
          {
              nul -> isa = false; nul -> num = 0;
              nul -> fa = nul -> ch[0] = nul -> ch[1] = nul;
              for (int i = 0; i <= MAXB; i++) nul -> data[i] = nul -> sum[i] = 0;
          }
      
          void get_sin(int now, double x, double y)
          {
              double jie = 1, f = -1, ci = 1;
              for (int i = 0; i <= MAXB; i++) {
                  if (i) jie *= i;
                  if (!(i & 1)) {
                      f = -f;
                      to[now] -> data[i] = sin(y);
                  }
                  else to[now] -> data[i] = cos(y);
                  to[now] -> data[i] *= f * ci;
                  to[now] -> data[i] /= jie;
                  ci *= x;
              }
          }
      
          void get_exp(int now, double x, double y)
          {
              double jie = 1, ci = 1;
              for (int i = 0; i <= MAXB; i++) {
                  if (i) jie = jie * i;
                  to[now] -> data[i] = ci * exp(y) / jie;
                  ci = ci * x;
              }
          }
      
          void get_xia(int now, double x, double y)
          {
              to[now] -> data[0] = y; to[now] -> data[1] = x;
              for (int i = 2; i <= MAXB; i++) to[now] -> data[i] = 0;
          }
      
          void build(int now, int tp, double x, double y)
          {
              to[now] = new Node;
              to[now] -> num = now; to[now] -> isa = false;
              to[now] -> fa = to[now] -> ch[0] = to[now] -> ch[1] = nul;
              if (tp == 1) get_sin(now, x, y);
              else if (tp == 2) get_exp(now, x, y);
              else get_xia(now, x, y);
              to[now] -> update();
          }
      
          void link(int x, int y)
          {
              to[x] -> be_rot(); to[x] -> splay();
              to[y] -> access(); to[y] -> splay();
              to[x] -> fa = to[y];
          }
      
          void del(int x, int y)
          {
              to[x] -> be_rot(); to[y] -> access();
              to[y] -> splay(); to[y] -> pushdown();
              to[y] -> ch[0] = nul; to[x] -> fa = nul; to[y] -> update();
          }
      
          void magic(int c, int f, double x, double y)
          {
              to[c] -> splay();
              if (f == 1) get_sin(c, x, y);
              else if (f == 2) get_exp(c, x, y);
              else get_xia(c, x, y);
              to[c] -> update();
          }
      
          void query(int u, int v, double x)
          {
              double ans = 0;
              if (to[u] -> find_rot() != to[v] -> find_rot()) {
                  puts("unreachable"); return;
              }
              to[u] -> be_rot(); to[v] -> access(); to[v] -> splay();
              double tmp = 1;
              for (int i = 0; i <= MAXB; i++) {
                  ans += tmp * to[v] -> sum[i];
                  tmp *= x;
              }
              printf("%.10lf\n", ans);
          }
      }
      
      int main()
      {
      #ifndef __LOCAL_TEST
          freopen("math.in", "r", stdin);
          freopen("math.out", "w", stdout);
      #endif
          T::main();
          in(n); in(m); scanf("%*s");
          for (int i = 1; i <= n; i++) {
              in(f); scanf("%lf%lf", &a, &b);
              T::build(i, f, a, b);
          }
          while (m--) {
              scanf("%s", type);
              if (type[0] == 'a') {in(u); in(v); u++; v++; T::link(u, v);}
              else if (type[0] == 'd') {in(u); in(v); u++; v++; T::del(u, v);}
              else if (type[0] == 'm') {in(c); in(f); c++; scanf("%lf%lf", &a, &b); T::magic(c, f, a, b);}
              else {in(u); in(v); u++; v++; scanf("%lf", &x); T::query(u, v, x);}
          }
          return 0;
      }
      
      
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值