zoukankan      html  css  js  c++  java
  • gcd,gcd(欧拉函数)

    Description

    给你两个数a,m;

    问你在 [0,m1]范围内有几个数 xx 满足gcd(a,m)=gcd(a+x,m);

    Input

    第一行一个整数TT;

    接下来TT行,每行两个整数a,ma,m;

    1a<m1e91≤a<m≤1e9

    Output

    针对每两个数,输出满足条件的xx的数量。

    Samples

    Input Copy
    3
    4 9
    5 10
    42 9999999967
    Output
    6
    1
    9999999966

    Hint

    对于第一个4 9:

    满足的x是:0 1 3 4 6 7 

    gcd(a,m)==gcd(a+x,m)由欧几里得算法

    gcd(m,(a+x)%m)=temp
    令(a+x)%m==k;//这里一个x对应一个k
    gcd(a,k)==temp;
    gcd(a/temp,k)==1转化位欧拉函数找与a/temp的互质的个数

    #pragma GCC optimize(1)
    #pragma GCC optimize(2)
    #pragma GCC optimize(3,"Ofast","inline")
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<bits/stdc++.h> 
    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=1e4+100;
    ll gcd(ll a,ll b){
        if(b==0){
            return a;
        }
        else{
            return gcd(b,a%b);
        }
    } 
    ll Euler(ll 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 T;
        scanf("%d",&T);
        //gcd(a,m)==gcd(a+x,m)
        //gcd(m,(a+x)%m)=temp
        //令(a+x)%m==k;//这里一个x对应一个k 
        //gcd(a,k)==temp;
        //gcd(a/temp,k)==1转化位欧拉函数找与a/temp的互质的个数 
        while(T--){
            ll a,m;
            scanf("%lld%lld",&a,&m);
            ll tmp=gcd(a,m);
            printf("%lld
    ",Euler(m/tmp));
        }
        return 0;
    }

    有一天ZKL遇到一道数学题。给定三个正整数a,b,m,问有多少个整数x满足0≤x<m并且gcd(a+b,m)=gcd(b-a+x,m)。但是这对于号称“数学天才”的ZKL来说过于简单了,所以现在她把这道问题抛给了你。

    gcd(a,b)代表a和b的最大公约数。

    Input

    第一行一个整数T代表有T组询问。(1T10)

    接下来T行每行三个整数a,b,m(1ab1012 , 1m1012)。

    Output

    T行,第i行代表第i组询问中,满足条件的x的数量

    Samples

    input 
    3 1 2 3 2 2 9 12 123 1234
    output 
    1 6 616
     
     
     令tmp=gcd(a+b,m),问你有几个x满足gcd(b-a+x,m)==tmp。根据欧几里得算法,gcd(b-a+x,m) == gcd(m,(b-a+x)%m)。此时我们令k=(b-a+x)%m,因为0<=x<m,所以我们可以发现一个x对应一个k,同时k的范围0<=k<m。然后我们就可以将题目转化为0<=k<m,求满足gcd(m,k)==tmp式子k的数量。我们可以发现当k == 0时与k == m时gcd(m,k)都等于m,于是我们可以将k的范围转化成0<k<=m,我们可以得到一下式子,再经过转化,我们可以得到所求即为小于等于(m/tmp)且与(m/tmp)互质的数的数量就是求φ(m/tmp)。
    在这里插入图片描述
     
     
     
     
     
     
     
    #pragma GCC optimize(1)
    #pragma GCC optimize(2)
    #pragma GCC optimize(3,"Ofast","inline")
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<bits/stdc++.h> 
    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=1e4+100;
    ll gcd(ll a,ll b){
        if(b==0){
            return a;
        }
        else{
            return gcd(b,a%b);
        }
    } 
    ll Euler(ll 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 T;
        scanf("%d",&T);
        //gcd(a,m)==gcd(a+x,m)
        //gcd(m,(a+x)%m)=temp
        //令(a+x)%m==k;//这里一个x对应一个k 
        //gcd(a,k)==temp;
        //gcd(a/temp,k)==1转化位欧拉函数找与a/temp的互质的个数 
        while(T--){
            ll a,b,m;
            scanf("%lld%lld%lld",&a,&b,&m);
            ll tmp=gcd(a+b,m);
            printf("%lld
    ",Euler(m/tmp));
        }
        return 0;
    }
  • 相关阅读:
    [Clr via C#读书笔记]Cp4类型基础
    [Clr via C#读书笔记]Cp3共享程序集和强命名程
    [Clr via C#读书笔记]Cp2生成打包部署和管理应用程序和类型
    [Clr via C#读书笔记]Cp1CLR执行模型
    试用Markdown来写东西
    字符编码的总结
    常去的网站
    Click Once使用总结
    【LevelDB源码阅读】Slice
    【程序员面试金典】面试题 01.05. 一次编辑
  • 原文地址:https://www.cnblogs.com/lipu123/p/13751545.html
Copyright © 2011-2022 走看看