终于等到你

众里寻他千百度,蓦然回首,那人却在灯火阑珊处。

数论一点点总结

数论基础

最大公约数Gcd

int gcd(int a, int b) //a大于b
{
	return a % b == 0 ? b : gcd(b, a % b);
}

最小公倍数Lcm

int Lcm(int a,int b)
{
return a/gcd(a,b)*b;
}

费马小定理

费马小定理(Fermat Theory)是数论中的一个重要定理,其内容为:假设p是质数(素数),且
Gcd(a,p)=1,那么a^(p-1) ≡1(mod p)。即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。该定理是1636年皮埃尔·德·费马发现的。 费马小定理在ACM数论题中应用还是较多的。

唯一分解定理

算术基本定理,又称为正整数的唯一分解定理,即:每个大于1的自然数均可写为质数的积,而且这些素因子按大小排列之后,写法仅有一种方式。(素数的分解方法唯一)例题Pairs Forming LCM运用到唯一分解定理的好题。

拓展的欧几里得算法

扩展欧几里得算法(英语:Extended Euclidean algorithm)是欧几里得算法(又叫辗转相除法)的扩展。已知整数a、b,扩展欧几里得算法可以在求得a、b的最大公约数的同时,能找到整数x、y(其中一个很可能是负数),使它们满足贝祖等式ax + by = \gcd(a, b).
如果a是负数,可以把问题转化成|a|(-x)+by=gcd(|a|,b),然后令 x'=(-x)。
通常谈到最大公约数时,我们都会提到一个非常基本的事实:给予二个整数a、b,必存在整数x、y使得ax + by = gcd(a,b)[1]。有两个数a,b,对它们进行辗转相除法,可得它们的最大公约数——这是周知的。然后,收集辗转相除法中产生的式子,倒回去,可以得到ax+by=gcd(a,b)的整数解。
例如:求一对正整数(x,y),使得ax+by=gcd(a,b)。
代码如下:

void exgcd(int a,int b,int &d,int & x,int & y)
{
if(!b){
d=a;x=1;y=0;
}
else {
exgcd(b,a%b,d,y,x);
y-=x*(a/b);
}
}

提示:设a #,b,c为任意整数,如果方程ax+by=c的一组整数解为(x0,y0),则它的任意整数解可以写成(x0+kb',y0-ka'),其中a'=a/gcd(a,b),b'=b/gcd(a,b),k取任意整数。

Eratosthenes筛法

筛法的思路的忒简单:对于不超过n的每个非负整数p,删除2p,3p,4p....当处理完所以的数之后,剩下的就是素数了。vis[i]表示i以及被删除,代码如下复杂度O(nlogn)

memset(vis,0,sizeof(vis));
for(int i=2;i<=n;i++)
for(int j=2*i;j<=n;j+=i)
vis[j]=1;

改进一点:p可以限定素数,如果是素数,则不进行第二重循环;内层循环也不必从i*2开始——它在i=2是以及被筛掉,代码如下:

int m=sqrt(n+0.5);
memset(vis,0,sizeof(vis));
for(int i=2;i<=m;i++)
if(!vis[i])
for(int j=i*i;j<+n;j+=i)
vis[j]=1;

素数定理

π(x)~x/ln(x)。
其中 ln x 为 x 的自然对数。上式的意思是当 x 趋近无限,π(x)与x/ln x的比值趋近 1。但这不表示它们的数值随着 x 增大而接近。
对正实数x,定义π(x)为素数计数函数,亦即不大于x的素数个数。

逆元(inv)

1.什么是逆元

当求解公式:(a/b)%m 时,因b可能会过大,会出现爆精度的情况,所以需变除法为乘法:
设c是b的逆元,则有bc≡1(mod m);
则(a/b)%m = (a/b)
1%m = (a/b)bc%m = ac(mod m);
即a/b的模等于a
b的逆元的模;
逆元就是这样应用的

2.求逆元的方法

(1).费马小定理

在是素数的情况下,对任意整数都有。 如果无法被整除,则有。 可以在为素数的情况下求出一个数的逆元,,即为逆元。
题目中的数据范围1<=x<=10^9,p=1000000007,p是素数;
所以x肯定就无法被p整除啊,所以最后就得出x^(p-2)为x的逆元啦。
复杂度O(logn)

const int mod = 1000000009;
long long quickpow(long long a, long long b) {

    if (b < 0) return 0;

    long long ret = 1;

    a %= mod;

    while(b) {

        if (b & 1) ret = (ret * a) % mod;

        b >>= 1;

        a = (a * a) % mod;

    }

    return ret;
}
long long inv(long long a) {

    return quickpow(a, mod - 2);

}
posted @ 2018-09-27 23:13  gzr2018  阅读(261)  评论(0编辑  收藏  举报