2021-05-12 acwing算法基础课 快速幂,扩展欧几里得,中国剩余定理,高斯消元

AcWing 875. 快速幂

1.题意:
2.题解:
3.ac代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long ll;
ll quick_pow(ll a,ll k,ll p){
    ll res=1;
    
    while(k){
        if(k&1) res=res*a%p;
        k>>=1;
        a=a*a%p;
    }
    return res;
}
int main(){
    ll a,b,p;
    int t;
    cin>>t;
    while(t--){
        cin>>a>>b>>p;
        cout<<quick_pow(a,b,p)<<endl;
    }
}

AcWing 876. 快速幂求逆元

1.题意:
2.题解:

欧拉公式?a与n互质,aphi(n)恒等于1(mod n)
费马定理,如果p是质数,a与p互质,则an-1恒等于1(mod n),
根据题意逆元即为an-2

3.ac代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int primes[N];
bool st[N];
int tot;
int phi[N];
typedef long long ll;
ll quick_pow(ll a,ll k,ll p){
    ll res=1;
    
    while(k){
        if(k&1) res=res*a%p;
        k>>=1;
        a=a*a%p;
    }
    return res;
}
void oula(int n){
    for(int i=2;i<=n;i++){
        if(!st[i]){
            primes[tot++]=i;
            phi[i]=i-1;
        }
        for(int j=0;primes[j]<=n/i;j++){
            st[primes[j]*i]=1;
            if(i%primes[j]==0){
                phi[primes[j]*i]=primes[j]*phi[i];
                break;
            }
            phi[primes[j]*i]=(primes[j]-1)*phi[i];
        }
    }
    
}
int main(){
    ll a,p;
    int t;
    cin>>t;
    //oula(100005);
    while(t--){
      cin>>a>>p;
      if(a%p!=0) cout<<quick_pow(a,p-2,p)<<endl;
      else cout<<"impossible"<<endl;
    }
}

AcWing 877. 扩展欧几里得算法

1.题意:
2.题解:

ax+by=gcd(a,b),对于a和b来说,一定存在正数x,y使得该式子成立,并且gcd是他们能构造的最小的正整数

3.ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void gcd(int a,int b,int &x,int &y){
    if(!b){
        x=1,y=0;
        return;
 
    }
    gcd(b,a%b,y,x);
    y=y-a/b*x;
   
}
int main(){
    int n,a,b,x,y;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a>>b;
        gcd(a,b,x,y);
        cout<<x<<" "<<y<<endl;
    
    }
}

AcWing 878. 线性同余方程

1.题意:
2.题解:

扩展欧几里得求线性同余ax恒等于b(mod m),求x
相当于ax-my=b —> ax+my=b;
求a,m的最小公倍数d,如果b是d的倍数,说明存在,否则就不存在,
切记求出的x是一种解,所以要求余m
ax+by=d
通解:x=x0-b/dk
y=y0+a/d
k

3.ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
ll gcd(ll a,ll b,ll &x,ll &y){
    if(!b){
        x=1,y=0;
        return a;
    }
    ll d=gcd(b,a%b,y,x);
    y=y-a/b*x;
    return d;
}
int main(){
    ll n,a,b,m,x,y;
    cin>>n;
    while(n--){
        cin>>a>>b>>m;
       // cout<<1<<endl;
        ll d=gcd(a,m,x,y);
        if(b%d==0){
            x=b/d*x%m;//!!注意%m,因为x有可能会爆
            cout<<x<<endl;
        }else{
            cout<<"impossible"<<endl;
        }
    }
}

AcWing 204. 表达整数的奇怪方式

1.题意:
2.题解:

卡了好久,又是因为没开longlong!!!
中国剩余定理orz,建议再做几遍,感觉还是没懂

3.ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
ll gcd(ll a,ll b,ll &x,ll &y){
    if(!b){
        x=1,y=0;
        return a;
    }
    ll d=gcd(b,a%b,y,x);
    y=y-a/b*x;
    return d;
}
ll mod(ll a,ll b){
    return (a%b+b)%b;
}
int main(){
    ll n,a1,a2;
    ll k1,k2,m1,m2;
    cin>>n;
    cin>>a1>>m1;
    
    for(int i=2;i<=n;i++){
        cin>>a2>>m2;
        ll d=gcd(a1,-a2,k1,k2);
        if((m2-m1)%d==0){
            k1=mod(k1*(m2-m1)/d,abs(a2/d));
            m1=k1*a1+m1;
            a1=abs(a1/d*a2);
        
        }else{
            cout<<-1<<endl;
            return 0;
        }
        
    }
    
    cout<<m1<<endl;
}

AcWing 883. 高斯消元解线性方程组

1.题意:
2.题解:
3.ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
const double eps=1e-6;
int n;
double a[110][110];
int guass(){
    int c=0,r=0;
    for(c=0,r=0;c<n;c++){
        int t=r;
        for(int i=r;i<n;i++){
            if(fabs(a[i][c])>fabs(a[t][c])) t=i;
        }
        if(fabs(a[t][c])<eps) continue;
        for(int i=c;i<=n;i++) swap(a[r][i],a[t][i]);
        for(int i=n;i>=c;i--){
            a[r][i]/=a[r][c];
        }
        for(int i=r+1;i<n;i++){
            if(fabs(a[i][c])>eps)
            for(int j=n;j>=c;j--){
                a[i][j]-=a[r][j]*a[i][c];
            }
        }
        r++;
    }
    if(r<n){
        for(int i=r;i<n;i++){
            if(fabs(a[i][n])>eps) return 0;//无解
        }
        return 1;//无穷解
    }
    for(int i=n-1;i>=0;i--){
        for(int j=i+1;j<n;j++){
            a[i][n]-=a[i][j]*a[j][n];
        }
    }
    // for(int i=0;i<n;i++){
    //     for(int j=0;j<=n;j++){
    //         cout<<a[i][j]<<" ";
    //     }
    //     cout<<endl;
    // }
    
    
    return 2;//唯一解
}
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<=n;j++){
            cin>>a[i][j];
        }
    }
    int t=guass();
    if(t==1){
        cout<<"Infinite group solutions"<<endl;
        
    }else if(t==0){
        cout<<"No solution"<<endl;
    }else if(t==2){
        for(int i=0;i<n;i++){
            printf("%.2lf\n",a[i][n]);
        }
    }
    
}

AcWing 884. 高斯消元解异或线性方程组

1.题意:
2.题解:

异或==没有进位的加法,可以高斯消元,只有0/1,不是减法,而是异或

3.ac代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
const int mod=1e9+7;
typedef long long ll;
int a[110][110];
int n;
int gauss(){
    int c,r;
    for(c=0,r=0;c<n;c++){
        int t=r;
        if(a[t][c]==0)
            for(int i=r;i<n;i++){
                if(a[i][c]>a[t][c]){
                    for(int j=c;j<=n;j++) swap(a[i][j],a[t][j]);
                    break;
                }
            }
        if(a[t][c]==0) continue;
        for(int i=r+1;i<n;i++){
            if(a[i][c]==1){
                for(int j=c;j<=n;j++) a[i][j]=a[i][j]^a[r][j];//建议倒叙!!
            }
        }
        r++;
    }
    
    if(r<n){
        for(int i=r;i<n;i++){//!!注意从r开始!!
            if(a[i][n]>0) return 0;
        }
        return 1;
    }
   
    for(int i=n-1;i>=0;i--){
        for(int j=i+1;j<n;j++){
            if(a[i][j]==1)
              a[i][n]=a[i][n]^a[j][n];
        }
    }
    // for(int i=0;i<n;i++){
    //     for(int j=0;j<=n;j++){
    //         cout<<a[i][j]<<" ";
    //     }
    //     cout<<endl;
    // }
    return 2;
}
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<=n;j++){
            cin>>a[i][j];
        }
    }
    int t=gauss();
    if(t==0){
        cout<<"No solution"<<endl;
    }else if(t==1){
        cout<<"Multiple sets of solutions"<<endl;
    }else{
        for(int i=0;i<n;i++){
            cout<<a[i][n]<<endl;
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值