zoukankan      html  css  js  c++  java
  • 数论欧拉函数专题

    题目网站

    欧拉函数

    欧拉函数模板一:

    求一个数的欧拉函数

    ll Eoula(int n) {
        ll res = n; 
        for (ll i = 2; i*i <= n; i++) {
            if (n % i == 0) {
                res = res / i * (i - 1);//先除防止数据溢出
                while (n % i == 0)n /= i;
            }
        }
        if (n > 1)res = res / n * (n - 1);
        return res;
    }

    欧拉函数模板二:

    打表法:

    const int maxn=1e6+100;
    const int mod=1000000007;
    int ol[maxn],prime[maxn],cnt=0;
    void oula(){//打表oula函数 
        ol[1]=1;
        for(int i=2;i<=42768;i++){
            if(!ol[i]){
                ol[i]=i-1;
                prime[++cnt]=i;
            } 
            for(int j=1;j<=cnt&&i*prime[j]<=42768;j++){
                if(i%prime[j]){
                    ol[i*prime[j]]=ol[i]*(prime[j]-1);
                }
                else{
                    ol[i*prime[j]]=ol[i]*prime[j];
                    break;
                }
            }
        }
    }

    A题:找新朋友

    A题就是一个模板题,就是求n的欧拉函数值

    AC代码:

    #pragma GCC optimize(1)
    #pragma GCC optimize(2)
    #pragma GCC optimize(3,"Ofast","inline")
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<queue> 
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    template <typename Tp>
    void read(Tp &x){//read(n);
        x=0;char ch=1;int fh;
        while(ch!='-'&&(ch>'9'||ch<'0')){
            ch=getchar();
        }
        if(ch=='-'){
            fh=-1;ch=getchar();
        }else fh=1;
        while(ch>='0'&&ch<='9'){
            x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
        }
        x*=fh;
    }
    inline char read1()//字符串读入挂
    {
        register char ch=getchar();
        while(ch<'A'||ch>'M')ch=getchar();
        return ch; 
    }
    const int maxn=1e6+100;
    const int mod=1000000007;
    int ol[maxn],prime[maxn],cnt=0;
    int n;
    void oula(){
        ol[1]=1;
        for(int i=2;i<=42768;i++){
            if(!ol[i]){
                ol[i]=i-1;
                prime[++cnt]=i;
            } 
            for(int j=1;j<=cnt&&i*prime[j]<=42768;j++){
                if(i%prime[j]){
                    ol[i*prime[j]]=ol[i]*(prime[j]-1);
                }
                else{
                    ol[i*prime[j]]=ol[i]*prime[j];
                    break;
                }
            }
        }
    }
    int main(){
        oula();
        int t;
        cin>>t;
        while(t--){
            int n;
            cin>>n;
            cout<<ol[n]<<endl;
        } 
    }
    View Code

    B题:B - GCD Again

    题目大意就是输入一个n求gcd(n,m)>1的m的个数,就是用n-oula(n)-1;

    #pragma GCC optimize(1)
    #pragma GCC optimize(2)
    #pragma GCC optimize(3,"Ofast","inline")
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<queue> 
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    template <typename Tp>
    void read(Tp &x){//read(n);
        x=0;char ch=1;int fh;
        while(ch!='-'&&(ch>'9'||ch<'0')){
            ch=getchar();
        }
        if(ch=='-'){
            fh=-1;ch=getchar();
        }else fh=1;
        while(ch>='0'&&ch<='9'){
            x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
        }
        x*=fh;
    }
    inline char read1()//字符串读入挂
    {
        register char ch=getchar();
        while(ch<'A'||ch>'M')ch=getchar();
        return ch; 
    }
    const int maxn=1e6+100;
    const int mod=1000000007;
    int ol[maxn],prime[maxn],cnt=0;
    void oula(){//打表oula函数 
        ol[1]=1;
        for(int i=2;i<=42768;i++){
            if(!ol[i]){
                ol[i]=i-1;
                prime[++cnt]=i;
            } 
            for(int j=1;j<=cnt&&i*prime[j]<=42768;j++){
                if(i%prime[j]){
                    ol[i*prime[j]]=ol[i]*(prime[j]-1);
                }
                else{
                    ol[i*prime[j]]=ol[i]*prime[j];
                    break;
                }
            }
        }
    }
    ll Eoula(int n) {//求φ(m/tmp)
        ll res = n; 
        for (ll i = 2; i*i <= n; i++) {
            if (n % i == 0) {
                res = res / i * (i - 1);//先除防止数据溢出
                while (n % i == 0)n /= i;
            }
        }
        if (n > 1)res = res / n * (n - 1);
        return res;
    }
    int main(){
        ll n; 
        while(cin>>n&&n){
            ll sum=Eoula(n);
            cout<<n-sum-1<<endl; 
        }
    } 
    View Code

     C题:C - Calculation 2

    求给定一个正整数N,计算小于N且与 N不互质的正整数之和。

    (a,n)=1,(na,n)=1

    证明:

    (a,n)=(na,a)=(na,n)(a,n)=(n−a,a)=(n−a,n)(更相减损法)

    由于gcd ⁡ ( a , n ) = gcd ⁡ ( n − a , n ) ,这说明不互质的数是成对出现的,且一对的和为n / 2,那么答案就是:

     具体证明

    #pragma GCC optimize(1)
    #pragma GCC optimize(2)
    #pragma GCC optimize(3,"Ofast","inline")
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<queue> 
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    template <typename Tp>
    void read(Tp &x){//read(n);
        x=0;char ch=1;int fh;
        while(ch!='-'&&(ch>'9'||ch<'0')){
            ch=getchar();
        }
        if(ch=='-'){
            fh=-1;ch=getchar();
        }else fh=1;
        while(ch>='0'&&ch<='9'){
            x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
        }
        x*=fh;
    }
    inline char read1()//字符串读入挂
    {
        register char ch=getchar();
        while(ch<'A'||ch>'M')ch=getchar();
        return ch; 
    }
    const int maxn=1e6+100;
    const int mod=1000000007;
    int ol[maxn],prime[maxn],cnt=0;
    void oula(){//打表oula函数 
        ol[1]=1;
        for(int i=2;i<=42768;i++){
            if(!ol[i]){
                ol[i]=i-1;
                prime[++cnt]=i;
            } 
            for(int j=1;j<=cnt&&i*prime[j]<=42768;j++){
                if(i%prime[j]){
                    ol[i*prime[j]]=ol[i]*(prime[j]-1);
                }
                else{
                    ol[i*prime[j]]=ol[i]*prime[j];
                    break;
                }
            }
        }
    }
    ll Eoula(int n) {//求φ(m/tmp)
        ll res = n; 
        for (ll i = 2; i*i <= n; i++) {
            if (n % i == 0) {
                res = res / i * (i - 1);//先除防止数据溢出
                while (n % i == 0)n /= i;
            }
        }
        if (n > 1)res = res / n * (n - 1);
        return res;
    }
    int main(){
        ll n;
        //3 1 2 
        //4 1 2 3 
        while(cin>>n&&n){
            ll ans=1ll*n*(n-1)/2-n*Eoula(n)/2; 
            cout<<ans%mod<<endl; 
        }
    }
    View Code

    D题:D - The Euler function

    就是求[a,b]之间的欧拉函数之和,打表法可以求

    #pragma GCC optimize(1)
    #pragma GCC optimize(2)
    #pragma GCC optimize(3,"Ofast","inline")
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<queue> 
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    template <typename Tp>
    void read(Tp &x){//read(n);
        x=0;char ch=1;int fh;
        while(ch!='-'&&(ch>'9'||ch<'0')){
            ch=getchar();
        }
        if(ch=='-'){
            fh=-1;ch=getchar();
        }else fh=1;
        while(ch>='0'&&ch<='9'){
            x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
        }
        x*=fh;
    }
    inline char read1()//字符串读入挂
    {
        register char ch=getchar();
        while(ch<'A'||ch>'M')ch=getchar();
        return ch; 
    }
    const int maxn=5e6+100;
    const int mod=1000000007;
    int ol[maxn],prime[maxn],cnt=0;
    void oula(){//打表oula函数 
        ol[1]=1;
        for(int i=2;i<=3000110;i++){
            if(!ol[i]){
                ol[i]=i-1;
                prime[++cnt]=i;
            } 
            for(int j=1;j<=cnt&&i*prime[j]<=3000110;j++){
                if(i%prime[j]){
                    ol[i*prime[j]]=ol[i]*(prime[j]-1);
                }
                else{
                    ol[i*prime[j]]=ol[i]*prime[j];
                    break;
                }
            }
        }
    }
    ll Eoula(int n) {//求φ(m/tmp)
        ll res = n; 
        for (ll i = 2; i*i <= n; i++) {
            if (n % i == 0) {
                res = res / i * (i - 1);//先除防止数据溢出
                while (n % i == 0)n /= i;
            }
        }
        if (n > 1)res = res / n * (n - 1);
        return res;
    }
    int main(){
        int a,b;
        oula(); 
        while(cin>>a>>b){
            ll ans=0;
            for(int i=a;i<=b;i++){
                ans+=ol[i];
            }
            cout<<ans<<endl;
        }
    }
    View Code

    E题:E - GCD

    题意:给定整数N和M,多少整数X满足1 <= X <= N和gcd(X,N)> = M。

    假设X和N的最大公约数为d

    gcd(N,X)>=m

    gcd(p*d,q*d)>=m 

    所以p和q是互质的

    所以就是找满足N=p*d,并且d>=m的p的欧拉函数之和(sqrt(N)的复杂度可以求)

    #pragma GCC optimize(1)
    #pragma GCC optimize(2)
    #pragma GCC optimize(3,"Ofast","inline")
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<queue> 
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    template <typename Tp>
    void read(Tp &x){//read(n);
        x=0;char ch=1;int fh;
        while(ch!='-'&&(ch>'9'||ch<'0')){
            ch=getchar();
        }
        if(ch=='-'){
            fh=-1;ch=getchar();
        }else fh=1;
        while(ch>='0'&&ch<='9'){
            x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
        }
        x*=fh;
    }
    inline char read1()//字符串读入挂
    {
        register char ch=getchar();
        while(ch<'A'||ch>'M')ch=getchar();
        return ch; 
    }
    const int maxn=1e6+100;
    const int mod=1000000007;
    int ol[maxn],prime[maxn],cnt=0;
    int n;
    void oula(){//打表oula函数 
        ol[1]=1;
        for(int i=2;i<=42768;i++){
            if(!ol[i]){
                ol[i]=i-1;
                prime[++cnt]=i;
            } 
            for(int j=1;j<=cnt&&i*prime[j]<=42768;j++){
                if(i%prime[j]){
                    ol[i*prime[j]]=ol[i]*(prime[j]-1);
                }
                else{
                    ol[i*prime[j]]=ol[i]*prime[j];
                    break;
                }
            }
        }
    }
    int Eoula(int n) {//求φ(m/tmp)
        int res = n;
        for (int i = 2; i*i <= n; i++) {
            if (n % i == 0) {
                res = res / i * (i - 1);//先除防止数据溢出
                while (n % i == 0)n /= i;
            }
        }
        if (n > 1)res = res / n * (n - 1);
        return res;
    }
    int main(){
        //假设他的最大公约数为d
        //gcd(n,x)>=m
        //gcd(p*d,q*d)>=m 
        //所以p和q是互质的
        //所以就是找满足n=p*d,并且d>=m的p的欧拉函数之和
        int t;
        cin>>t; 
        while(t--){
            int n,m;
            cin>>n>>m;
            int ans=0;
            for(int i=1;i*i<=n;i++){
                if(n%i==0){
                    if(i>=m){
                        ans+=Eoula(n/i);
                    }
                    if((n/i)>=m&&(n/i)!=i){
                        ans+=Eoula(i);
                    }
                }
            }
            cout<<ans<<endl;
        } 
    } 
    View Code

     F题:A - Primitive Roots

    原根个数

    给定一个奇素数,求他的原根的个数,其中,一个数n的原根是指一个小于n的正整数x,若有x^1mod n,x^2 mod n...x^n-1 mod n刚好是n-1的一个全排列,

    那么就称x是n的一个原根。

    解题思路:这里用到了两个定理,第一个是奇素数一定有原根,第二个是一个数n的原根的个数ans=euler(euler(n)),由于是一个奇素数,因此ans=euler(n-1)。

     

    #pragma GCC optimize(1)
    #pragma GCC optimize(2)
    #pragma GCC optimize(3,"Ofast","inline")
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<queue> 
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    template <typename Tp>
    void read(Tp &x){//read(n);
        x=0;char ch=1;int fh;
        while(ch!='-'&&(ch>'9'||ch<'0')){
            ch=getchar();
        }
        if(ch=='-'){
            fh=-1;ch=getchar();
        }else fh=1;
        while(ch>='0'&&ch<='9'){
            x=(x<<1)+(x<<3)+ch-'0';ch=getchar();
        }
        x*=fh;
    }
    inline char read1()//字符串读入挂
    {
        register char ch=getchar();
        while(ch<'A'||ch>'M')ch=getchar();
        return ch; 
    }
    const int maxn=1e6+100;
    const int mod=1000000007;
    int ol[maxn],prime[maxn],cnt=0;
    void oula(){//打表oula函数 
        ol[1]=1;
        for(int i=2;i<=42768;i++){
            if(!ol[i]){
                ol[i]=i-1;
                prime[++cnt]=i;
            } 
            for(int j=1;j<=cnt&&i*prime[j]<=42768;j++){
                if(i%prime[j]){
                    ol[i*prime[j]]=ol[i]*(prime[j]-1);
                }
                else{
                    ol[i*prime[j]]=ol[i]*prime[j];
                    break;
                }
            }
        }
    }
    ll Eoula(int n) {//求φ(m/tmp)
        ll res = n; 
        for (ll i = 2; i*i <= n; i++) {
            if (n % i == 0) {
                res = res / i * (i - 1);//先除防止数据溢出
                while (n % i == 0)n /= i;
            }
        }
        if (n > 1)res = res / n * (n - 1);
        return res;
    }
    int main(){
        ll n; 
        while(cin>>n&&n){
            cout<<Eoula(n-1)<<endl; 
        }
    } 
    View Code

     

     

     

     

  • 相关阅读:
    Iterator迭代器与增强for循环
    java中的集合
    基本类型包装类、System类
    java之Calendar类
    java二维数组
    java学习之字符串缓冲区
    java学习之内部类、包与代码块
    DataGridView列增加单选按钮、输入框
    DataGridView加上默认的序号
    数据结构简介
  • 原文地址:https://www.cnblogs.com/lipu123/p/13756346.html
Copyright © 2011-2022 走看看