zoukankan      html  css  js  c++  java
  • 数学计算 LibreOJ

    题目描述

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

    1 m: x=x×m ,输出 xmodM ;

    2 pos: x=x/ 第 pos 次操作所乘的数(保证第 pos 次操作一定为类型 1,对于每一个类型 1 的操作至多会被除一次),输出 xmodM 。

    Input

    一共有 t 组输入。
    对于每一组输入,第一行是两个数字 Q,M 。
    接下来 Q 行,每一行为操作类型 op ,操作编号或所乘的数字 m (保证所有的输入都是合法的)。

    Output

    对于每一个操作,输出一行,包含操作执行后的 xmodM 的值

    Example

    样例输入

    1
    10 1000000000
    1 2
    2 1
    1 2
    1 10
    2 3
    2 4
    1 6
    1 7
    1 12
    2 7

    样例输入

    2
    1
    2
    20
    10
    1
    6
    42
    504
    84

    Hint

    对于 20% 的数据, 1≤Q≤500 ;
    对于 100% 的数据, 1≤Q≤105,t≤5,M≤109 。

    分析

    这道题最简单的做法应该就是线段树了
    对于第i次操作
    如果是操作1,我们将编号为i的节点乘m,维护一个单点修改,最后输出区间乘积
    如果是操作2,我们把编号为i的节点的权值改为1可以了,因为每一个节点只会修改一次,同样是输出区间乘积

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+5;
    ll m,mod,q;
    struct tre{
        ll l,r,val;
    }tr[maxn<<2];
    void push_up(ll da){
        tr[da].val=(tr[da<<1].val%mod*tr[da<<1|1].val%mod);
    }
    void build(ll da,ll le,ll ri){
        tr[da].l=le;
        tr[da].r=ri;
        if(le==ri){
            tr[da].val=1;
            return;
        }
        ll mids=(le+ri)>>1;
        build(da<<1,le,mids);
        build(da<<1|1,mids+1,ri);
        push_up(da);
    }
    void gai(ll da,ll bh,ll w){
        if(tr[da].l==tr[da].r){
            tr[da].val=w%mod;
            return;
        }
        ll mids=(tr[da].l+tr[da].r)>>1;
        if(bh<=mids) gai(da<<1,bh,w);
        else gai(da<<1|1,bh,w);
        push_up(da);
    }
    void gai2(ll da,ll bh,ll w){
        if(tr[da].l==tr[da].r){
            tr[da].val=tr[da].val%mod*w%mod;
            return;
        }
        ll mids=(tr[da].l+tr[da].r)>>1;
        if(bh<=mids) gai(da<<1,bh,w);
        else gai(da<<1|1,bh,w);
        push_up(da);
    }
    ll qh(ll da,ll le,ll ri){
        if(le<=tr[da].l && ri>=tr[da].r){
            return tr[da].val%mod;
        }
        ll ans=1;
        ll mids=(tr[da].l+tr[da].r)>>1;
        if(le<=mids) ans=ans*qh(da<<1,le,ri)%mod;
        if(ri>mids) ans=ans*qh(da<<1|1,le,ri)%mod;
        return ans%mod;
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            scanf("%lld%lld",&q,&mod);
            build(1,1,q);
            for(ll i=1;i<=q;i++){
                ll t;
                scanf("%lld%lld",&t,&m);
                if(t==1){
                    gai2(1,i,m);
                    printf("%lld
    ",qh(1,1,i)%mod);
                } else {
                    gai(1,m,1);
                    printf("%lld
    ",qh(1,1,i)%mod);
                }
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    C#中直接调用VB.NET的函数,兼论半角与全角、简繁体中文互相转化<收藏>
    C# Passing Associative Arrays to PL/SQL Code
    Executing a PL/SQL Function
    一个oracle 学习网站 收藏
    C# Retrieving Associative Arrays from PL/SQL Code
    向oracle 数据库写入 LOBs 数据
    Oracle 11g如何赢得.NET开发人员的青睐?
    使用C#进行Reflection编程
    反射(Reflection
    四种简单的排序算法
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/12963640.html
Copyright © 2011-2022 走看看