牛客竞赛 发电(逆元)(树状数组)

Posted 行码棋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客竞赛 发电(逆元)(树状数组)相关的知识,希望对你有一定的参考价值。

本题涉及逆元知识,点击链接

数论知识总结

欧几里得算法详解

树状数组知识,请点击链接

树状数组详解

题目链接

用树状数组维护前n个的乘积模上mod

  • 做添加操作时:

让树状数组tr[]乘上要增加的倍数,还必须做取模操作,所以结果存的是前n项的乘积取模之后的结果。

  • 做删除操作时

因为之前存的是模之后的结果,删除是除法运算,不能直接进行除法运算,所以要求逆元。

因为模数是素数,所以

\\frac{a}{p}= a*p^{mod-2} 必须是mod为素数才可以用这个公式

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int N = 1e6+5;
ll tr[N];
int n,m;
//快速幂
ll qpow(ll a,ll b)
{
    ll res = 1;
    while(b)
    {
        if(b&1)res = res*a%mod;
        b >>= 1;
        a = a*a%mod;
    }
    return res;
}
//树状数组添加操作
void add(ll x,ll y)
{
    while(x<=n)
    {
        tr[x]=tr[x]*y%mod;//注意是乘法操作,结果还要取模
        x += x&-x;
    }
}
//查询操作
ll sum(ll x)
{
    ll res = 1;
    for(int i=x;i>0;i-=i&-i)
        res = res*tr[i]%mod;
    return res;
}

int main()
{
    scanf("%d%d",&n,&m);
    int x,y,z;
    for(int i=1;i<=n;i++) tr[i]=1;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        if(x==1)
            add(y,z);
        else if(x==2)//除以z等价于乘上z的mod-2次方取模的结果
            add(y,qpow(z,mod-2)%mod);
        else
            printf("%lld\\n",sum(z)*qpow(sum(y-1),mod-2)%mod);
    }
    return 0;
}

以上是关于牛客竞赛 发电(逆元)(树状数组)的主要内容,如果未能解决你的问题,请参考以下文章

如何在原数组的基础上生成树状数组

牛客多校2021 F.xay loves trees(树状数组+树上的滑动窗口)

牛客竞赛语法入门班数组字符串习题完结

牛客练习赛7 E珂朵莉的数列(树状数组+爆long long解决方法)

牛客14612 string AC自动机 + 树状数组

牛客竞赛语法入门班数组栈队列和stl习题未完成