集训过半了,信息量太大了。。。
-
快速幂
两种方法
-
递归实现
Intpow(int a,int b) { If(b==0) return 1; //边界 Int tmp; tmp=pow(a,b/2); tmp=(tmp*tmp); if(b%2==1) //b是奇数 tmp=tmp*a; return tmp; }
2) 位运算(更简洁)
Int pow(int a,int b)
{
Int r=1,base=a;
While(b)
{
if(b&1) r*base;
Base*=base;
b>>=1;
}
Return r;
}
-
素数
1)素数的判定
list[]={2,3,5,7,11,…};//素数表
boolisprime(int x)
{
int i=1;
While(list[i]*list[i]<=x)
{
If(x%list[i]==0)
return false;
i++;
}
return true;
}
2) 欧拉筛法(求x范围内的质数)
void getprime(int x)
{
memset(isprime,true,sizeof(isprime));
for(inti=2;i<=x;i++)
if(isprime[i])
for(int j=i<<1;j<=x;j+=i) isprime[j]=false;
for(inti=2;i<=x;i++)
if(isprime[i])
prime[++size]=i;//加入素数表
}
-
gcd,最大公因数
1) 欧几里得算法
int gcd(int a,int b)
{
if(b==0) return a;
Return gcd(b,a%b);
}
2) 二进制最大公约数算法(更快)
具体思想:
若a、b都是偶数,则gcd(a,b)=2*gcd(a/2,b/2)
若a是奇数、b是偶数,则gcd(a,b)=gcd(a/2,b/2)
若a、b都是奇数,则gcd(a,b)=gcd((a-b)/2,b)
int gcd(inta,int b)
{
int c=1;
while(a-b) //ab不等
{
if(a&1)
{
if(b&1) //a奇b奇
{
if(a>b)a=(a-b)>>1;
else b=(b-a)>>1;
}
else //a奇b偶
b>>=1;
}
else
{
if(b&1) //a偶b奇
a>>=1;
else //a偶b偶
c<<=1,a>>=1,b>>=1;
}
}
return c*a;
}
-
约数
1)约数个数
int nums(int a)
{
int k=2,res=1,p;
while(k*k<=a)
{
p=1;
while(n%k==0) {a/=k;p++}
res*=p;
k++;
}
if(a>1) res*=2;
return res;
}
2)求约数和
int nums(int a)
{
int k=2,n=a,sum=0;
while(k*k<=n)
{
while(a%k==0) {a/=k;sum=sum+k+n/k;}
k++;
}
return sum;
}
互质同余(一堆性质) //提高篇P175
-
威尔逊定理与费马小定理
1)威尔逊定理
(p-1)! ≡ p-1 ≡ -1(mod p)
2)费马小定理
a^(p-1)≡a^0≡1(mod p)
a^x≡a^(x%(p-1))(mod p)
-
欧拉函数(可怕)
定义:欧拉函数是小于等于n的数中与n互质的数的个数,用φ(n) 表示欧拉函数值
若a,m为正整数,且gcd(a,m) = 1,则a^φ(m)≡1(modm)
我们亦可以利用欧拉定理来简化幂模运算:a^x≡a^(x%φ(m))(mod m)
我们将a^x≡a^(x%φ(m))(mod m)变下形:
由于a^φ(m)≡1(modm),a^x≡a^(x%φ(m))≡a^(x%φ(m)+φ(m))(modm)
-
求欧拉函数
哈哈还没搞懂,挖坑
先写数论吧,图论暂时放着,因为真的是太多了(实在不会用csdn,以后慢慢摸索好了,用了word文档,突然想到为什么不用的Dev-c++,word上打代码累死了QAQ)(啊终于把排版弄得好看一点了#2018.10.7)