• 欧拉函数模板


    洛谷P3601 签到题

    数论里面,对于 l 和 r 很大,r-l 范围又很小的时候,都用到了用一个数组x[ i ]表示 i+l 的值,也就是把 l~r 这个区间对应到 0~l-1 中了。

    同时也预处理了可能对答案做出贡献的值(一般是预处理根号内的素数)。

    与这道题很相似:

    洛谷P1835 素数密度_NOI导刊2011提高(04)

    #include<bits/stdc++.h>
    using namespace std;
    #define N 1000005
    #define ll long long
    #define ri register int
    int cnt=0,ans=0,pri[N],su[N],fl[N];
    ll l,r;
    void suu(int n)
    {
        for(ri i=2;i<=n;++i){
            if(!pri[i]) su[++cnt]=i;
            for(ri j=1;j<=cnt&&su[j]*i<=n;++j){
                pri[su[j]*i]=1;
                if(i%su[j]==0) break;
            }
        }
    }
    int main()
    {
        scanf("%lld%lld",&l,&r);
        suu(sqrt(r));
        for(int i=1;i<=cnt;++i){
            for(ll j=l/su[i]*su[i];j<=r;j+=su[i]){
                if(j>=l && j!=su[i]) fl[j-l]=1;
            }
        }
        for(ll i=l;i<=r;++i) if(fl[i-l]==0) ans++;
        printf("%d
    ",ans);
    }
    /*
    2 11
    */
    筛大素数

    这道题也是一样,已知求单个欧拉的公式与其质因子有关,就预处理出 1~sqrt(r)的素数,然后枚举素数进行更新。

    (注意题中要求的是与其不互质的数,用它本身减一下就行了)

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define mod 666623333
    #define N 1000005
    ll l,r,su[N],phi[N],pri[N],tmp[N],cnt=0;
    void init()
    {
        ll x=sqrt(r);
        for(ll i=2;i<=x;++i){
            if(!pri[i]) su[++cnt]=i;
            for(ll j=1;j<=cnt&&su[j]*i<=x;++j){
                pri[su[j]*i]=1;
                if(i%su[j]==0) break;
            }
        }
    }
    void calc_phi()
    {
        for(ll i=0;i<=r-l;++i) tmp[i]=i+l,phi[i]=i+l;
        for(ll i=1;i<=cnt;++i){
            ll ln=l/su[i]*su[i],rn=r/su[i]*su[i];
            for(ll j=ln;j<=rn;j+=su[i]){//很像筛大素数的思路 预处理出可能做出贡献的值 跳着更新 把时间降到nlogn 
                if(j<l) continue;
                phi[j-l]=phi[j-l]/su[i]*(su[i]-1);//利用公式计算 
                while(tmp[j-l]%su[i]==0) tmp[j-l]/=su[i];
            }
        }
        for(ll i=0;i<=r-l;++i) 
        if(tmp[i]>1) phi[i]=phi[i]/tmp[i]*(tmp[i]-1);
    }
    int main()
    {
        ll ans=0;
        scanf("%lld%lld",&l,&r);
        init();
        calc_phi();
        for(ll i=0;i<=r-l;++i) ans=(ans+i+l-phi[i])%mod;
        printf("%lld
    ",ans);
    }
    /*
    233 2333
    */
    签到题

     

    P5091 【模板】欧拉定理

    求a^m %mod 的时候,m过大,就可以由欧拉定理将m变成一个小于mod的数:

    图片来源

    然后就是一个裸的板子了:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll phi,fl=0;
    ll read()
    {
        ll x=0; char ch=getchar();
        while(ch<'0'||ch>'9'){ if(ch=='-') fl=-1; ch=getchar(); }
        while(ch<='9'&&ch>='0'){
            x=(x*10+ch-'0');
            if(x>=phi) fl=1,x%=phi;
            ch=getchar();
        } 
        return x;
    }
    ll quick_pow(ll a,ll k,ll mod)
    {
        ll ans=1;
        while(k){ if(k&1) ans=ans*a%mod; a=a*a%mod; k>>=1; }
        return ans;
    }
    ll calc_phi(ll x)//求单个欧拉 
    {
        ll ans=x;
        for(ll i=2;i<=sqrt(x);++i)
        if(x%i==0){
            ans=ans/i*(i-1);
            while(x%i==0) x/=i;
        }
        if(x>1) ans=ans/x*(x-1);
        return ans;
    }
    int main()
    {
        ll a,m,b;
        scanf("%lld%lld",&a,&m);
        phi=calc_phi(m);
        b=read();
        printf("%lld
    ",quick_pow(a,b+fl*phi,m));
    }
    /*
    998244353 12345 98765472103312450233333333333
    */
    欧拉定理
  • 相关阅读:
    如何在Ubuntu下通过USB连接iPone/iPod
    全手动封装教程+SRS9.80102 文本教程(适合初学)
    PHP 面试踩过的坑
    视频 | 一步步教你操作websocket通知案例
    在职场,辞退你、培养你,从来不是看能力
    git撤销本地修改与回退版本
    异步发送邮件完整示例
    如何解决Redis缓存和MySQL数据一致性的问题?
    PHP 面试踩过的坑(二)
    守护进程、信号和平滑重启
  • 原文地址:https://www.cnblogs.com/mowanying/p/11544873.html
Copyright © 2020-2023  润新知