• 洛谷 P1082 同余方程


    题目描述

    求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解。

    输入输出格式

    输入格式:

    输入只有一行,包含两个正整数 a, b,用一个空格隔开。

    输出格式:

    输出只有一行,包含一个正整数 x0,即最小正整数解。输入数据保证一定有解。

    输入输出样例

    输入样例#1:
    3 10
    输出样例#1:
    7

    说明

    【数据范围】

    对于 40%的数据,2 ≤b≤ 1,000;

    对于 60%的数据,2 ≤b≤ 50,000,000;

    对于 100%的数据,2 ≤a, b≤ 2,000,000,000。

    NOIP 2012 提高组 第二天 第一题

    //智商太低,搞这个搞了一晚上……

    解题思路

      我太菜了,不会扩欧,用的是dalao教的费马小定理,但这题没规定b一定是质数,所以要用欧拉定理,费马小定理其实就是欧拉定理的特殊情况。

        1、同余的传递性。

            若$$a equiv bmod p $$        且$$c equiv bmod p $$        则$$ a equiv cmod p$$

        2、欧拉定理(同余的那个)$$a^{phi(b)} equiv 1mod b$$

        3、题目要求的那个式子$$ax equiv 1mod b$$

      以上三项代换一下得到$ax equiv a^{phi(b)} mod{b}$,我不知道为什么左边的a可以除过去——$x equiv a^{phi(b)-1}mod b$,于是最小的x就是$a^{phi(b)-1}mbox{%} b$。

    源代码

    #include<stdio.h>
    #include<time.h>
    #include<math.h>
    #include<algorithm>
    #include<cstring>
    #define ll long long
    long long phi(long long n)
    {
        ll res=n,now=n,max=ceil(sqrt(n));
        int b[max+1],size=0;ll prime[max/2];
        memset(b,1,sizeof(b));b[1]=0;
        for(int i=2;i<=max;i++){//不筛素数表会TLE一个点,本机要跑44s……
            if(b[i]==0) continue;
            size++;prime[size]=i;
            for(int t=2*i;t<=max;t+=i) b[t]=0;
        }
        for(int i=1;i<=size;i++){
            if(now%prime[i]==0){
                res=res/prime[i]*(prime[i]-1);
                while(now%prime[i]==0){
                    now/=prime[i];
                }
            }
            if(now==1) break;
        }
        if(now!=1) res=res/now*(now-1);
        return res;
    }
    
    long long p(long long n,long long k,long long mo)
    {
        if(k==0) return 1;
        if(k==1) return n%mo;
        long long a=p(n,k>>1,mo)%mo;
        a=a*a%mo;
        //printf("%lld %lld
    ",k,a);
        return a*p(n,k&1,mo)%mo;
    }
    
    int main()
    {
        //freopen("mod.in","r",stdin);
        //freopen("mod.out","w",stdout);//cogs的印记……
        long long a,b;
        //double start=clock();
        scanf("%lld%lld",&a,&b);
        long long k=phi(b)-1;
        //printf("%lf
    ",(clock()-start)/1000000);
        printf("%lld
    ",(p(a,k,b)+b)%b);
        return 0;
    }
  • 相关阅读:
    巧用数据流让 Word 文档在线阅读
    《开源公开课分享》:Java开源框架案例分享
    存储过程
    opencv求取RGB分量
    opencv中的矩阵操作
    三维高斯模型 opencv实现
    线性均值滤波和中值滤波的比较
    opencv 画延长线
    MATLAB曲线绘制
    如何在博客园发博客时插入优酷视频
  • 原文地址:https://www.cnblogs.com/wawcac-blog/p/7074852.html
Copyright © 2020-2023  润新知