写笔记,写笔记!!!
1.欧拉函数
欧拉函数:求 1~N中与N互质的数的个数
公式:
证明如下:利用容斥原理
答案代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
{
int n;
cin>>n;
while(n--){
int a;
cin>>a;
LL res=a;
for(int i=2;i*i<=a;i++){
if(a%i==0){
while(a%i==0) a/=i;//a能整除i
res=res*(i-1)/i;//通分后的形式
}
}
if(a>1) res=res*(a-1)/a;
cout<<res<<endl;
}
return 0;
}
2.筛法求欧拉函数(线性筛)
正整数 𝑛,求 1∼n 中每个数的欧拉函数之和
① p是质数, phi(p) = 1 - p
② i % p == 0, phi(p*i) = p * phi(i)
③ i % p != 0, phi(p*i) = p*(1 - 1/p) + phi(i)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e7 + 10;
int primes[N], cnt;
int euler[N];
bool st[N];
//线性筛质数的变式
void get_eulers(int n){
euler[1] = 1;
for(int i = 2; i <= n; i ++){
if(!st[i]){
primes[cnt ++] = i;//①
euler[i] = i - 1;//phi
}
for(int j = 0; primes[j] <= n/i; j ++ ){
int t = primes[j] * i;
st[t] = true;
if(i % primes[j] == 0){
euler[t] = euler[i] * primes[j];//②
break;
}
euler[t] = euler[i] * (primes[j] - 1);//③
}
}
}
int main(){
int n;
cin >> n;
get_eulers(n);
ll res = 0;
for(int i = 1; i <= n; i ++) res += euler[i];
cout<<res<<endl;
return 0;
}
3.快速幂 O(log b)
其实就是二进制计算!!!!!,b的二进制位置0不计入结果,1则计入结果
求解:快速求a^b % p 用pow会超时
任何数都可以用二进制表示,把b用二进制表示
b = 2^0 + 2^1 +....+26logb
a^b = a^(2^0 + 2^1 +....+26logb) 对数的运算法则
= a^2^0 * a^2^1 *......
解释:若 b 不为空,则进入循环; 判读二进制b的末尾是否为1(是否为奇数),若是证明二进制表示该位需要乘,则res结果乘了;只要进入了循环则a更新下一位
LL qmi(LL a, LL b, LL p){
while(b){
if(b & 1) res = res * a % p;//二进制末位为1 要乘
b >>= 1;//右移
a =a * a % p;//a^(2^0), a^(2^1)...乘上当前本身得到下一个
}
return res;
}
4.快速幂求逆元
逆元定义:
若整数 b,m 互质,并且对于任意的整数 𝑎,如果满足 𝑏|𝑎,则存在一个整数 x,使得 )𝑎/𝑏≡𝑎×𝑥(mod𝑚),则称 𝑥 为 𝑏 的模 𝑚 乘法逆元,记为 𝑏^−1(mod𝑚)。
𝑏 存在乘法逆元的充要条件是 𝑏 与模数 𝑚 互质。当模数 𝑚 为质数时,𝑏^𝑚−2 即为 𝑏 的乘法逆元。
要求解本题,先要了解一下费马定理:
如果b和p互质,则b的p-1次方模p等于1
从而,本质上是求一个快速幂。。。。。。。
b,p不互质 无解,b是p的倍数
qmi(a, p - 2, p)