中国剩余定理与素数筛

本文介绍了中国剩余定理在解决同余方程组问题上的应用,通过实例展示了如何使用C++实现洛谷曹冲称象题的解法。同时,文章还探讨了两种不同的素数筛选方法,包括埃氏筛法和欧拉筛法,并给出了相应的C++代码实现。这两种算法在寻找素数时具有不同的效率特点。
摘要由CSDN通过智能技术生成

中国剩余定理,也叫孙子定理,之所以叫这个名字,是因为《孙子算经》中有这样一个问题:

有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?

这个被叫做“物不知数”的问题本质上是解下面的同余方程组

 下面以洛谷曹冲称象的题为例,求给定n个模与n个余数,求解x,x mod r1=a1类似这种

要保证x能够对n个数都成立,即把x1,x2,...,xn每个数求出特解,最后加起来mod r1*r2*...rn即可
随意先把每个余数乘起来得r,要保证对每个数对剩余n-1个数mod成立,设p=r/a【i】,px0 mod r1求x0,因为r1与p互质,所以求出逆元即可,最后乘上p乘上r1得出x1,加起来对r取模即可。

#include<stdio.h>
using namespace std;
typedef long long ll;
inline ll exgcd(ll a,ll b ,ll &x,ll &y){
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    ll d=exgcd(b,a%b,y,x);
    y-=(a/b)*x;
    return d;
}
inline ll inv(ll a,ll p){
    ll x, y;
    exgcd(a,p,x,y);
    return (x%p+p)%p;
}
inline ll CRT(ll a[],ll b[],ll n){
    ll r=1,x=0;
    for(int i=0;i<n;++i){
        r*=a[i];
    }
    for(int i=0;i<n;++i){
        ll p=r/a[i];
        x+=(b[i]*p*inv(p,a[i]))%r;
        
    }
    return x%r;
}
int main(){
    int  n;
	ll a[15],b[15];
    scanf("%d",&n);
    for(int i=0;i<n;++i){
        scanf("%lld%lld",a+i,b+i);
    }
    printf("%lld",CRT(a,b,n));
    return 0;
}

 这是洛谷上的一道模板题(p1495)

素数筛

1.埃氏筛法

#include<stdio.h>
#include<vector>
#include<stack>
using namespace std;
const int MAXN=1e7+5;
typedef long long ll;
int vis[MAXN];
void asshai(int n){
	for(int i=2;i<=n;i++){
	if(!vis[i]){
		for(int j=i*i;j<=n;j+=i){
			vis[j]=1;
		}  
    }      
}
}
int main()
{
	asshai(5050);
	for(int i=2;i<=50;i++)
	if(!vis[i])printf("%d\n",i);
	return 0;
}

2.欧拉筛(线性筛)(效率更高)

#include<stdio.h>
#include<vector>
#include<stack>
#include<string.h>
using namespace std;
const int MAXN=1e7+5;
typedef long long ll;
vector<int>primes;
bool vis[MAXN];
void oulashai(int n){
	for(int i=2;i<=n;i++){
		if(vis[i]==0)
		      primes.push_back(i);
		for(int p : primes){
			if(p*i>n)break;
			vis[i*p]=1;
			if(i%p==0)break;
		}	
		} 
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    oulashai(100);
    while(m--){
    	int k;
    	scanf("%d",&k);
    	printf("%d\n",primes[k-1]);
	}    
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值