把该书中一些很短巧实用的代码;
筛选法求素数:
memset(vis,0,sizeof(vis));
for (int i=2;i<=n;i++){
for (int j=i*2;j<=n;j+=i) vis[j]=1;
}
//升级版
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/lnx;
三种求模:
(a+b)%n=(a%n+b%n)%n;
(a-b)%n=(a%n-b%n+n)%n;
a*b%n=a%n*(b%n)%n;//乘法注意不要越界!!
大数例如10的100次方取模:
将大数例如1234表示为(((1*10+2)*10+3)*10+4),然后利用上述公式求结果;
快速幂取模,循环实现,原理就是把指数分解为二进制数表示,代码如下:
long long quick_mod(long long a,long long b){
long long res=1;
while(b!=0){
if (b%2==1) res*=(a%n);
a=a*(a%n);
b/=2;
}
return res;
}
但是当数据量大于10^19时,longlong会爆,所以利用快速乘法,原理类似,a*b就是b个a相加,将b表示为二进制:
int n;
long long mul(long long a,long long b){
long long res=0;
while(b!=0){
if(b%2==1) res=(res+a%n)%n;
a=(a%n+a%n)%n;
b/=2;
}
return res;
}
long long quick_mod(long long a,long long b){
long long res=1;
while(b!=0){
if (b%2==1) res=mul(res,a)%n;
a=mul(a,a);
b/=2;
}
return res;
}
唯一分解定理:
又称为正整数的唯一分解定理,即:每个大于1的自然数均可写为质数的积,而且这些素因子按大小排列之后,写法仅有一种方式。
所以一个数可以表示成一个已知质数数组(刷选法得到)得到的数组e,e里面存各个质数的指数,比如15表示为e{1,1,0,0...}的方式;
void fenjie(int n){
for(int i=0;i<primes.size();i++){
while(n%primes[i]==0){
n/primes[i];
e[i]++;
}
if (n==1) break;
}
}