中国剩余定理,也叫孙子定理,之所以叫这个名字,是因为《孙子算经》中有这样一个问题:
有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?
这个被叫做“物不知数”的问题本质上是解下面的同余方程组:
下面以洛谷曹冲称象的题为例,求给定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;
}