您的位置:首页 > 其它

简单数论知识梳理(省选复习)

2017-03-23 21:14 218 查看
(noip数论算法汇总)

①扩展欧几里得

int ex_gcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1,y=0;
return a;
}
int g=ex_gcd(b,a%b,x,y);
int t=x;x=y,y=t-a/b*y;
return g;
}
应用及要点:

one :   求形如ax+by=gcd(a,b)的一组解(x,y)  (有解情况当且仅当ab互质)

    要注意的是,已知一组解(x0,y0),则其他所有解都可以表示成(x0+k*b,y0-k*a)

    想像成直线就可以理解了

two:    求逆元,ax≡1 mod(p) 可以转化为 ax-py=1

另:

辗转相除和辗转相减法两个定理:

辗转相减法:gcd(a,b)=gcd(a-b,b)

辗转相除法:gcd(a,b)=gcd(a%b,b)

②分解质因数

O(sqrt(n))太无脑了无视掉

O(n)预处理和O(log(a))分解:

线性筛法预处理 dy[i] 表示i的最小质因子在prime数组中的编号

分解时每次除以最小质因子即可做到log的分解质因数

代码:



void init()
{
for(int i=2;i<=n;i++)
{
if(!vis[i])prime[++cnt]=i;
for(int j=1;j<=cnt;j++)
{
long long tmp=prime[j]*i;
if(tmp>=N)break;
vis[tmp]=1,dy[tmp]=j;
if(tmp%prime[j]==0)break;
}
}
}
int num
;
void work(int x)
{
while(x!=1)
{
num[dy[x]]++;
x/=prime[dy[x]];
}
}


③逆元:

常用的有三种,扩展欧几里得上面提到了,下面只写费马小定理和线性递推求逆元

费马小定理:a^(p-2)是a在膜p意义下的逆元,即a^(p-1)%p=1

ll qm(ll a,ll b)
{
ll ret=0,t=a;
while(b)
{
if(b&1)ret=ret*t%mod;
t=t*t%mod;b>>=1;
}return ret;
}
ll inv(ll x){return qm(x,mod-2); }
线性递推逆元:  inv[1]=1,inv[i]=inv[p%i]*(p-p/i)%p

让我来认真的证明一次上式.....(noip前真的是差到连这玩意都不会证.......)

设 t=p/i,k=p%i

则 p=t*i+k

即 (t*i+k)≡0(mod p)

=>  -t*i≡k(mod p)

两边同时除以i*k

=> -t*inv[k]≡inv[i](mod
p)

故inv[i]=-t*inv[k](mod
p)

转成正数:inv[i]=(-t+p)*inv[k](mod
p)

所以 inv[i]=(p-p/i)*inv[p%i](mod
p)

可以愉快的线性推逆元啦23333

int inv
;
void init()
{
inv[1]=1;
for(int i=2;i<mod;i++)
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
④欧拉函数:

 线性筛求欧拉函数前面一篇博客里已经提到过,在此不提

欧拉函数的意义:

phi
=小于n的数中与n互质的数的个数

定义式:

phi
=n*(1-1/p1)*(1-1/p2)*(1-1/p3)....(1-1/pk)

这很简单就不放代码了。

应用:

one :上一个求逆元中还有一种方法没有说到就是欧拉函数。

   有欧拉定理:a^φ(n)  ≡ 1 mod n 

two : 按定义,求小于n且与n互质的数的个数(2333)

three:求n以内与n互质的数的和

    有公式:sum(n)=phi(n)*n/2; (sum(n)为小于n的所有与n互质的数的和)

⑤一些实用的定理:

约定:

唯一分解式形为n=p1^a1*p2^a2*p3^a3*…*pk^ak

约数个数定理: n的约数个数=(a1+1)*(a2+1)*(a3+1)....(ak+1)

约数和定理:     n的约数和=(p1^0+p1^1+p1^2...p1^a1)*(p2^0+p2^1+p2^2....p2^a2)...(pk^0+pk^1...pk^ak)

基础的数论知识差不多就是这些了,后面几篇博客会对几个重要的数论知识点进行详解或较多例题复习

⑥等比数列求和的分治算法:

定理:

对于Sn=a^1+a^2+...+a^n

当n==0时Sn=1;n==1时Sn=a

当n为偶数时:

Sn=S(n/2)*(a^(n/2)+1)

当n为奇数时:

Sn=S(n/2)*(a^(n/2+1)+1)+(a^(n/2)+1)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: