逆元和同余定理的记忆

文章有问题/////////

 

 

 

快速幂取余

ll ksm(long long x,long long a,long long p){//快速幂取余
    ll ans=1;
    x=x%p;
    while(a>0){
        if(a&1){
            ans=(ans*x)%p;
        }
        x=(x*x)%p;
        a>>=1;

    }
    return ans;

}

高精度取模

#include
#include
#include
using namespace std;
 
int main(){
    string a;
    int b;
    cin >> a >> b;
    int len = a.length();
    int ans = 0;
    for(int i = 0; i < len; i++){
        ans = (ans * 10 + a[i] - '0') % b;
    }
    printf("%d\n",ans);
    return 0;
}

逆元计算/扩展欧几里德算法

#include 
#include
#include
#include
long long m,x,y;

using namespace std;

void ggcd(int a,int b){
    if(b==0){
        x=1;
        y=0;
        return;
    }
    else{

        ggcd(b,a%b);
        long long temp=x;
        x=y;//相当于x1=y2
        y=temp-(a/b)*y;//相当于y1=x2-(a/b)*y2

    }//x即为逆元
}

思考:
(个人理解)

扩展欧几里德算法

欧几里德有一个定理:gcd(a,b)=gcd(b,a%b);

这段程序就是解决(a × x)+(b× y)=gcd(a,b);

 

 

逆元

求式子(a/b)%m的时候,由于b过大会出现爆精度的现象,有时为了精度也会用b的逆元去求式子。

b的逆元可以看作b在这个式子里的又一个倒数,b的逆元会满足原式=(a×b)%m,但b并不是数学意义上的b的倒数,b的倒数往往是一个小数,而b的逆元不会这样。但是在这里b的逆元又满足这个式子。

同余定理

(a + b) % m = (a % m + b % m) % m

(a * b) % m = ((a % m) * (b % m)) % m

这个好理解QAQ

题目

1.    51nod1256 乘法逆元

给出2个数M和N(M < N),且M与N互质,找出一个数K满足0 < K < N且K * M % N = 1,如果有多个满足条件的,输出最小的。

解:真——求乘法逆元。。代码如下

#include 
#include
#include
#include
long long m,x,y;

using namespace std;

void ggcd(int a,int b){
    if(b==0){
        x=1;
        y=0;
        return;
    }
    else{

        ggcd(b,a%b);
        long long temp=x;
        x=y;//相当于x1=y2
        y=temp-(a/b)*y;//相当于y1=x2-(a/b)*y2

    }
}
int main(){
    long long n,h;
    scanf("%lld %lld",&n,&m);
    ggcd(n,m);
    while(x<0){
        x=(x+m)%m;
    }
    printf("%lld\n",x);
    return 0;
}

2.     51nod1013 3的幂的和

求:3^0 + 3^1 +...+ 3^(N) mod 1000000007

解:Sn=a1*(1-q^(n+1))/(1-q);q=3,a1=1,化简(q^(n+1)-1)/2;即这个式子对1000000007去余。

先求出2对1000000007的逆元,然后快速幂求q^(n+1)(因为(q^(n+1)太大了,所以在求的过程中一直对1000000007取余,防止爆精度),再-1,乘以2的逆元,最后对1000000007取余;代码如下:

#include 
#include
#include
#include

using namespace std;
typedef long long ll;
const int mod=1000000007;
long long X,y;
long long gcd(long long a,long long b){//计算逆元
    int t,d;
    if(b==0){
        X=1;
        y=0;
return a;
    }
        d=gcd(b,a%b);
        t=X;
        X=y;//相当于x1=y2
        y=t-(a/b)*y;//相当于y1=x2-(a/b)*y2
return d;
}
ll ksm(long long x,long long a,long long p){//快速幂取余
    ll ans=1;
    x=x%p;
    while(a>0){
        if(a&1){
            ans=(ans*x)%p;
        }
        x=(x*x)%p;
        a>>=1;

    }
    return ans;

}

int main(){
    long long n;
    scanf("%lld",&n);
    gcd(2,mod);//2%m    原式化简得(q^(n+1)-1)/ 2%m, 所以求2对mod的逆元;
    if(X<0){//
        X+=mod;
    }
    n++;
    ll ans=(ksm(3,n,mod)-1)*X%mod;//所以原式就变成了(q^(n+1)-1)×x(逆元)%m;
    printf("%lld\n",ans);
    return 0;
}

 

你可能感兴趣的:(逆元)