zoukankan      html  css  js  c++  java
  • P4588 [TJOI2018]数学计算 题解

    旅行传送门:https://www.luogu.com.cn/problem/P4588

    题目描述

    小豆现在有一个数 x,初始值为 1。小豆有 Q 次操作,操作有两种类型:

    1 m:将 x 变为 x * m,并输出 x mod M

    2 pos:将 x 变为 x 除以第 pos 次操作所乘的数(保证第 pos 次操作一定为类型 1,对于每一个类型 1 的操作至多会被除一次),并输出 x mod M

    输入格式

    一共有 t 组输入。

    对于每一组输入,第一行是两个数字 Q,M

    接下来 Q 行,每一行为操作类型 op,操作编号或所乘的数字 m(保证所有的输入都是合法的)。

    输出格式

    对于每一个操作,输出一行,包含操作执行后的 x mod M 的值。

    输入输出样例

    输入 #1
    1
    10 1000000000
    1 2
    2 1
    1 2
    1 10
    2 3
    2 4
    1 6
    1 7
    1 12
    2 7
    输出 #1
    2
    1
    2
    20
    10
    1
    6
    42
    504
    84

    说明/提示

    对于 20% 的数据,≤ ≤ 500。

    对于 100% 的数据,≤ ≤ 10^5,≤ 5,≤ 10^9。

    解题思路

    第一眼看去,就只对一个数进行操作,这哪是甚么线段树的题,直接上暴力模拟不就完事了(上了就去见祖宗,哪怕开long long也直接亲ma炸穿)(虽然纯当作数论题做也不是不行)。

    但转念一想,蓝题不可能这么水,重新审题,题目中有两个操作,一是x乘以一个值,另一个是x除以之前乘过的某个值;乘以一个数又除以一个数,相当于啥也没干,也就可以看成是回溯操作。那么我们不妨以时间为轴建立一棵范围为[1,Q]的线段树,第k个叶子节点的序号表示这是第pos次操作,其存储的值表示x在这次操作中乘以的数。此时第一种操作变为给当前叶节点赋值m,第二种操作变为令第pos个叶节点的值回溯至1,根节点的值就是每次操作执行后x的值。

    总的来说是道很有意思的题_(:з」∠)_

    AC代码

     1 #include <bits/stdc++.h>
     2 #define FOR(i, j, k) for (int i = (j); i <= (k); i++)
     3 #define MAXQ 100000 + 10
     4 
     5 typedef long long ll;
     6 
     7 ll t, q, mod;
     8 ll tree[MAXQ << 2];
     9 
    10 ll read()
    11 {
    12     ll x = 0, f = 1;
    13     char ch = getchar();
    14     while (ch < '0' || ch > '9')
    15     {
    16         if (ch == '-')
    17             f = -1;
    18         ch = getchar();
    19     }
    20     while (ch >= '0' && ch <= '9')
    21     {
    22         x = x * 10 + ch - '0';
    23         ch = getchar();
    24     }
    25     return x * f;
    26 }
    27 
    28 void build(ll k, ll l, ll r)
    29 {
    30     tree[k] = 1;
    31     if (l == r)
    32         return;
    33     ll mid = (l + r) >> 1;
    34     build(k << 1, l, mid);
    35     build(k << 1 | 1, mid + 1, r);
    36 }
    37 
    38 void update(ll k, ll l, ll r, ll pos, ll x)
    39 {
    40     if (l == r)
    41     {
    42         tree[k] = x;
    43         return;
    44     }
    45     ll mid = (l + r) >> 1;
    46     if (pos <= mid)
    47         update(k << 1, l, mid, pos, x);
    48     else
    49         update(k << 1 | 1, mid + 1, r, pos, x);
    50     tree[k] = ((tree[k << 1] % mod) * (tree[k << 1 | 1] % mod)) % mod;
    51 }
    52 
    53 int main(int argc, char const *argv[])
    54 {
    55     t = read();
    56     while (t--)
    57     {
    58         q = read(), mod = read();
    59         build(1, 1, q);
    60         FOR(i, 1, q)
    61         {
    62             ll op = read();
    63             if (op == 1)
    64             {
    65                 ll m = read();
    66                 update(1, 1, q, i, m);
    67                 printf("%lld\n", tree[1] % mod);
    68             }
    69             else
    70             {
    71                 ll pos = read();
    72                 update(1, 1, q, pos, 1);
    73                 printf("%lld\n", tree[1] % mod);
    74             }
    75         }
    76     }
    77     return 0;
    78 }
    View Code
  • 相关阅读:
    java面向对象第三章
    java基础(9)
    java基础(8)
    java基础(7)
    java基础(6)
    Java(20)file i/o
    Java(19)JDBC
    Java(18) 集合框架
    Java(17)异常
    Java(16)接口
  • 原文地址:https://www.cnblogs.com/Foreign/p/14586167.html
Copyright © 2011-2022 走看看