前言:不知道为什么,最近几场比赛都是数学场,整的我和自闭儿一样......
昨天牛客的比赛有一个关于欧拉降幂的题,因为是知识盲区再加上喝了假酒,于是寄。
正文:
在学欧拉降幂之前要知道什么是欧拉函数。
在数论,对正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目(φ(1)=1)。
求欧拉函数的两个方法
方法一:线性求解
前置定理:
如果 ,其中
为质数,则
,否则
线性求解只用在欧拉筛上加一点东西就行,代码如下:
vector<int>phi(2e5+1);
phi[1] = 1;//初始化
vector<int>primes(2e5+1);
function<void()>prepare=[&](){
int j=-1;
for(int i = 2; i <= 2e5; i++){
if(primes[i]==0){
primes[++j]=i;
phi[i]=i-1;
}
for(int t = 0;t <= j && primes[t]*i <= 2e5; t++){
primes[i * primes[t]] = 1;
if(i % primes[t] == 0){
phi[i*primes[t]] = primes[t]*phi[i];
break;
}
else phi[i*primes[t]] = (primes[t] - 1)*phi[i];
}
}
};
方法二: 单点求解
前置定理:
若 ,其中
为质数,则
。
代码如下:
function<void(ll)>getphi=[&](ll x){
ll ans=x;
for(int i = 2;i*i <= x;i++){
if(x % i == 0){
ans = ans - ans / i;
while(x % i == 0) x /= i;
}
}
if(x != 1)ans = ans - ans/x;
return ans;
};
欧拉降幂
关于欧拉降幂,主要要记住这么几个结论(这里就不证明了,以前我尝试证明每一个数学结论,然后发现当时明白了,过几天又忘,还整的自己生不如死)
公式一
若
公式二:
若 且
公式三:
若 且
后记:
在学欧拉降幂的时候,我突然发现我的快速幂的写法是有问题的。
原来的快速幂板子:
ll ksm(ll a,ll b){
ll kase = 1 ;
while(b){
if(b&1){
kase = kase * a %mod;
}
a = a*a %mod;
b>>=1;
}
return kase ;
}
这样写会出现这样的情况,当mod=1,b=0,的时候,输出的不是0。
解决方案:
ll ksm(ll a,ll b){
ll kase = 1 ;
while(b){
if(b&1){
kase = kase * a %mod;
}
a = a*a %mod;
b>>=1;
}
return kase%mod ;
}