算法导论机考复习(数据处理)

素数筛选

求所有小于n的素数

#include<bits/stdc++.h>
using namespace std;
const int N=1000;
int prim[N];
int n;
int main()
{
    while(cin>>n)
    {
        //初始化2到n都是素数
        for(int i=2;i<=n;i++)
        {
            prim[i]=1;
        }
        //从2到n把所有的是当前数的倍数的数都设置为0
        //不能设置自己为0
        for(int i=2;i<=n;i++)
        {
            for(int j=2;j<=n;j++)
            {
                if(j%i==0&&i!=j)
                {
                    prim[j]=0;
                }
            }
        }
        for(int i=2;i<=n;i++)
        {
            if(prim[i])
            {
                cout<<i<<" ";
            }
        }
    }
}

扩展欧几里得算法

gcd=gcd(a,b);

那么存在gcd=ax+by;扩展欧几里得算法要求求出gcd,并且可以求出所有xy的解;

根据欧几里得算法我们知道gcd(a,b)=gcd(b,a%b)

那么就有b*x1+(a%b)*x2=gcd

又a%b=a-(a/b)*b;

将a%b进行替换,得到

gcd=a*y1+b*(x1-a/b*y1)

进而可以写出递归方程:

现在考虑递归终止

因为欧几里得算法就是在b=0的时候返回a,扩展欧几里得算法的最终状态就是

a*1+b*0=gcd;//不断递归达到的状态,然后反向递归求出xy,x就是a关于m的逆元

#include<bits/stdc++.h>
using namespace std;
const int N=1000;
int egcd(int a,int b,int &x,int &y)//xy都是可修改的
{
    if(b==0)
   {
       x=1;
       y=0;
       return a;
   }
        
    else
    {
        int ans=egcd(b,a%b,x,y);
        //注意这里更新xy的操作的位置,
        //因为ab的值是由上一层得到的,所以在参数里面就改了
        //而xy的值是在下一层得到的,所以在递归调用之后更新。
        int t=x;
        x=y;
        y=t-a/b*y;
        returna ans;
    }
    //根据扩展欧几里得:这一层的xy可以由下一层的得到
    
}

扩展欧几里得算法来求乘法逆元:

给出一个式子 ax ≡ 1 (mod m) 这个式子等价于 ax+my=1;

扩展欧几里得中有:

上面那个式子的解是:x=x0+(m/1)*t     y=y0+(a/1)*t

这样可以得知所有符合条件的x的解都是关于m同余的;

此时x是a关于m的乘法逆元,那么我们可以得到一定存在一个最小的解,而且这个解是小于m的;

总的来说扩展偶欧几里得算法就是求一个方程的解。

通过不断递归求出a*1+b*0=1这个状态,然后反向递归求出x,即为a关于m的乘法逆元

 

#include<bits/stdc++.h>
using namespace std;
const int N=1000;
int a,b,x,y;
int egcd(int a,int b,int &x,int &y)
{
    if(b==0)
        {
            x=1;
            y=0;
            return a;
        }
    else
    {
        int ans=egcd(b,a%b,x,y);
        //注意这里更新xy的操作的位置,
        //因为ab的值是由上一层得到的,所以在参数里面就改了
        //而xy的值是在下一层得到的,所以在递归调用之后更新。
        int t=x;
        x=y;
        y=t-a/b*y;
        return  ans;
    }
    //根据扩展欧几里得:这一层的xy可以由下一层的得到

}

int main()
{
    cin>>a>>b;
    cout<<(egcd(a,b,x,y)==1?(x%b+b)%b:-1)<<endl;
    //x可能超过b了,所以取模,取模之后可能会是负数,所以加上b,然后再取模,保证范围
    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值