码迷,mamicode.com
首页 > 其他好文 > 详细

ACM学习历程—HDU5475 An easy problem(线段树)(2015上海网赛08题)

时间:2015-10-06 18:01:27      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

Problem Description

One day, a useless calculator was being built by Kuros. Let‘s assume that number X is showed on the screen of calculator. At first, X = 1. This calculator only supports two types of operation.
1. multiply X with a number.
2. divide X with a number which was multiplied before.
After each operation, please output the number X modulo M.

 

 

Input

The first line is an integer T(1≤T≤10), indicating the number of test cases.
For each test case, the first line are two integers Q and M. Q is the number of operations and M is described above. (1≤Q≤105,1≤M≤109)
The next Q lines, each line starts with an integer x indicating the type of operation.
if x is 1, an integer y is given, indicating the number to multiply. (0<y≤109)
if x is 2, an integer n is given. The calculator will divide the number which is multiplied in the nth operation. (the nth operation must be a type 1 operation.)

It‘s guaranteed that in type 2 operation, there won‘t be two same n.

 

 

Output

For each test case, the first line, please output "Case #x:" and x is the id of the test cases starting from 1.
Then Q lines follow, each line please output an answer showed by the calculator.

 

 

Sample Input

1

10 1000000000

1 2

2 1

1 2

1 10

2 3

2 4

1 6

1 7

1 12

2 7

 

 

Sample Output

Case #1:

2

1

2

20

10

1

6

42

504

84

 

题目主要是出现的除法,在模条件下是不能进行除法的,除非存在逆元可以实现除法,但是此处除数不一定与被除数互质。

但是如果过程中不模的话,就要使用大数,会T。

考虑到题目中提到了,除数不会出现相同的。

也就是如果乘了1,2,3,然后再除掉2的话,结果就是由1和3构成,这样就不用考虑每个数的情况了,此时的每个数就是一个整体,结果只和这个数有没有出现有关。

于是可以考虑用线段树来维护分段的积。当某一个数被除掉了,所有与这个数相关的区间都要重新计算,最多有log(q)个区间。

这样效率就是qlogq,是满足条件的。

 

代码:

 

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <string>
#define LL long long

using namespace std;

const int maxN = 100005;
int q, m;
int op[maxN], top;

//线段树
struct node
{
    int lt, rt;
    LL val;
}tree[4*maxN];

//向上更新
void pushUp(int id)
{
    tree[id].val = (tree[id<<1].val*tree[id<<1|1].val)%m;
}

//建立线段树
void build(int lt, int rt, int id)
{
    tree[id].lt = lt;
    tree[id].rt = rt;
    tree[id].val = 1;//每段的初值,根据题目要求
    if (lt == rt)
    {
        //tree[id].add = ??;
        return;
    }
    int mid = (lt+rt)>>1;
    build(lt, mid, id<<1);
    build(mid+1, rt, id<<1|1);
    pushUp(id);
}

void add(int lt, int rt, int id, int pls)
{
    if (lt <= tree[id].lt && rt >= tree[id].rt)
    {
        if (pls)
        {
            tree[id].val *= pls;
            tree[id].val %= m;
        }
        else
            tree[id].val = 1;
        return;
    }
    int mid = (tree[id].lt+tree[id].rt)>>1;
    if (lt <= mid)
        add(lt, rt, id<<1, pls);
    if (rt > mid)
        add(lt, rt, id<<1|1, pls);
    pushUp(id);
}

void work()
{
    build(1, q, 1);
    top = 1;
    int d, y;
    for (int i = 0; i < q; ++i)
    {
        scanf("%d%d", &d, &y);
        if (d == 1)
            add(top, top, 1, y);
        else
            add(y, y, 1, 0);
        op[top++] = y;
        printf("%I64d\n", tree[1].val);
    }
}

int main()
{
    //freopen("test.in", "r", stdin);
    int T;
    scanf("%d", &T);
    for (int times = 1; times <= T; ++times)
    {
        printf("Case #%d:\n", times);
        scanf("%d%d", &q, &m);
        work();
    }
    return 0;
}

 

ACM学习历程—HDU5475 An easy problem(线段树)(2015上海网赛08题)

标签:

原文地址:http://www.cnblogs.com/andyqsmart/p/4857403.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!