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;
    }
  • 相关阅读:
    sizeof--返回一个数据类型或变量占用的字节数
    跳出循环break continue
    c-for循环
    while循环语句
    什么是Python中的套接字编程?
    详解Vue八大生命周期钩子函数
    你应该知道的数仓安全
    云图说|华为云自研云数据库GaussDB NoSQL,兼容多款NoSQL接口的数据库服务
    又到一年“粽子节”,快来测测你包的粽子颜值几分
    云小课 | 华为云KYON之私网NAT网关
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7267759.html
Copyright © 2011-2022 走看看