zoukankan      html  css  js  c++  java
  • 3813: 奇数国|树状数组|欧拉函数

    题目显然让求

    φi=lrai

    能够用线段树维护一下乘积然后求逆元再求欧拉函数,用压位的方法能够缩小60倍的常数。

    考虑一下树状数组的做法。由于仅仅有60个质因子,所以能够开60个树状数组维护每个质因子,最初维护了前缀的乘积然后T飞了。由于乘法比起加法还是比較慢的所以能够维护一个前缀的指数和,这样就能够在BZOJ成功卡进最后一页QAQ,然而UOJ的Extra Test还是过不了(应该是我写的代码太丑的原因吧。。

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<map>
    #define ll long long
    #define mod 19961993
    #define N 100001
    using namespace std;
    int sc()
    {
        int i=0,f=1; char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
        return i*f;
    }
    int prime[66],inv[66],b[300],top;
    int tr[61][N],n,Q,a[N],flag;
    ll cal(ll x,ll y)
    {
        ll ans=1;
        for(;y;x=x*x%mod,y>>=1)
            if(y&1)ans=ans*x%mod;
        return ans;
    }
    void change(int x,int y,ll v)
    {
        for(;y<N;y+=y&-y)tr[x][y]+=v;
    }
    ll ask(int  x,int y)
    {
        ll ans=0;
        for(;y;y-=y&-y)ans+=tr[x][y];
        return ans;
    }
    void solve(int p,ll x,int i,int f)
    {
        ll now=0;
        while(x%prime[i]==0)x/=prime[i],now++;
        change(i,p,f*now);
    }
    int main()
    {
        for(int i=2;i<=281;i++)
            if(!b[i])
            {
                prime[++top]=i;inv[top]=cal(prime[top],mod-2);
                for(int j=2*i;j<=281;j+=i)b[j]=1;
            }
        for(int i=1;i<N;i++)change(2,i,1),a[i]=3;
        Q=sc();
        while(Q--)
        {
            if(sc())
            {
                int x=sc(),y=sc();
                for(int i=1;i<=60;i++)
                {
                    if(a[x]%prime[i]==0) solve(x,a[x],i,-1);
                    if(y%prime[i]==0) solve(x,y,i,1);
                }
                a[x]=y;
            }
            else
            {
                int l=sc(),r=sc();
                ll ans=1;
                for(int i=1;i<=60;i++)
                {
                    ll res=ask(i,r)-ask(i,l-1);
                    if(res)
                        ans=ans*cal(prime[i],res-1)*(prime[i]-1)%mod;
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    【转】浏览器的渲染:过程与原理
    DOMContentLoaded、ready、load事件的区别
    ES6中export default 与export区别
    require一个node模块什么时候需要加上.default
    【转】函数防抖与函数节流
    【转】JavaScript函数柯里化的一些思考
    【原】javascript笔记之splice和slice这两兄弟为毛这么难记
    【转】JS 的 new 到底是干什么的?
    【原】移动端vue页面点透事件
    【转】用 async/await 来处理异步
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7267759.html
Copyright © 2011-2022 走看看