枚举因子法
bool judge(int n)
{
if(n==1) return false;
for(int i=2;i*i<=n;i++)
{
if(n%i==0) return false;
}
return true;
}
要把1特判掉。 可以1秒内单次判断1~10^16以内的任意一个素数是否是素数
素数筛:提前处理1~N的全体素数,后可以直接判断是否是素数
const int N=1000001;
bool notprime[N];
void init()
{
notprime[1]=1;
for(int i=2;i
mertens定理
https://wenku.baidu.com/view/c167c17931b765ce05081473.html看一波,嗯,这种东西看不懂还是要看的,不求甚解
可以一秒内10^7以内的质数和合数分离开来,接下来让每个合数只删除一次
欧拉筛(线性筛)每一个素数只被记录一次,每一个合数只会被一个唯一的最小素因子标记一次。
https://wenku.baidu.com/view/4881881daaea998fcc220e99.html 原理还是可以看一下的
大致上讲:每一个数有唯一的最大因子,被唯一筛去,唯一最大因子*小于等于最小质因子就是对应的合数,且筛全了
用了反证。
const int N=1000001;
bool notprime[N];
int prime[N];
int pn;
void init()
{
pn=0;
notprime[1]=1;
for(int i=2;i
1秒钟处理从10^7~10^8
#include
最大公约数:
设两数为a、b(a>b),用
表示a,b的最大公约数,r=a (mod b) 为a除以b的余数,k为a除以b的商,即
。辗转相除法即是要证明
。
第一步:令
,则设
第二步:根据前提可知
第三步:根据第二步结果可知,
也是
的因数
第四步:可以断定
与
互质(这里用反证法进行证明:设
,则
,则
,则a与b的一个公约数
,故c非a与b的最大公约数,与前面结论矛盾,因此c也是b与r的最大公约数)从而可知
,继而
。
证毕
注:以上步骤的操作是建立在刚开始时
的基础之上的,即m与n亦互质。
百度上的解释,海星,不用想了。
int gcd(int a,int b)
{
if(b==0) return a;
return gcd(b,a%b);
}
多个数求最大公约数
int gcd(int a,int b)
{
if(b==0) return a;
return gcd(b,a%b);
}
int multi_gcd(int a[],int n)
{
int res=gcd(a[0],a[1]);
for(int i=2;i
最小公倍数略。
扩展欧几里得算法:
把这个实现和Gcd的递归实现相比,发现多了下面的x,y赋值过程,这就是扩展欧几里德算法的精髓。
可以这样思考:
对于a'=b,b'=a%b 而言,我们求得 x, y使得 a'x+b'y=Gcd(a',b')
由于b'=a%b=a-a/b*b (注:这里的/是程序设计语言中的除法)
那么可以得到:
a'x+b'y=Gcd(a',b') ===>
bx+(a - a / b * b)y = Gcd(a', b') = Gcd(a, b) ===>
ay +b(x - a / b*y) = Gcd(a, b)
因此对于a和b而言,他们的相对应的p,q分别是 y和(x-a/b*y)
使用扩展欧几里德算法解决不定方程的办法
对于不定整数方程pa+qb=c,若 c mod Gcd(a, b)=0,则该方程存在整数解,否则不存在整数解。
有种较为不严谨的方法证明,不过至少弥补了一点空白,望某些数论大师补充修改:
由于我们知道,存在一组x与y使得a*x+b*y=gcd(a,b)。
将等式两边同时乘以整数k,即a*x*k+b*y*k=gcd(a,b)*k。如果c mod gcd(a,b)=f,则0<=f 那么可以令c=gcd(a,b)*k+f。这样一来,就有a*x*k+b*y*k+f=c。 若f 0,由于f 所以f=0,即只有当c mod gcd(a,b)=0时,a*x+b*y=c有正整数解。得证。 上面已经列出找一个整数解的方法,在找到p * a+q * b = Gcd(a, b)的一组解p0,q0后,p * a+q * b = Gcd(a, b)的其他整数解满足: p = p0 + b/Gcd(a, b) * t q = q0 - a/Gcd(a, b) * t(其中t为任意整数) 至于pa+qb=c的整数解,只需将p * a+q * b = Gcd(a, b)的每个解乘上 c/Gcd(a, b) 即可,但是所得解并不是该方程的所有解,找其所有解的方法如下: 在找到p * a+q * b = Gcd(a, b)的一组解p0,q0后,可以 得到p * a+q * b = c的一组解p1 = p0*(c/Gcd(a,b)),q1 = q0*(c/Gcd(a,b)),p * a+q * b = c的其他整数解满足: p = p1 + b/Gcd(a, b) * t q = q1 - a/Gcd(a, b) * t(其中t为任意整数) p 、q就是p * a+q * b = c的所有整数解。 上面是百度上的https://baike.baidu.com/item/扩展欧几里德算法/1053275?fr=aladdin比较透彻 线性同余方程,求逆元 分解质因数 算术基本定理https://baike.baidu.com/item/算术基本定理/10920095?fr=aladdin 这个写的通俗易懂,不错。 预处理素数筛 快速幂 费马小定理 模素数是有循环节的,P-1 https://baike.baidu.com/item/欧拉函数 baby step giant stephttps://www.cnblogs.com/wondove/p/7976525.html 不行了,看看其他人博客吧int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;y=0;
return a;
}
int d=exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return d;
}
int solve(int a,int b,int n)
{
int d=gcd(a,n);
if(b%d==0) return -1;
int k=b/d;
int x,y;
exgcd(a,n,x,y);
return x*k;
}
int p[100];
int e[100];
int cnt;
int fenjie(int n)
{
cnt=0;
for(int i=0;i
long long pow_mod(long long a,long long n,long long m)
{
long long res=1;
while(n>0)
{
if(n%2==1) res=res*a%m;
a=a*a%m;
n/=2;
}
return res;
}
int getphi(int n)
{
int ans=n;
for(int i=2;i*i<=n;i++)
{
if(n%i==0)
{
ans-=ans/i;
while(n%i==0)
n/=i;
}
}
if(n>1) ans-=ans/n;
return ans;
}