活动 - AcWing
目录
一、质数
1.试除法判断质数(易超时)
bool is_prime(int x)
{
if (x < 2) return false;
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0)
return false;
return true;
}
2.试除法分解质因数
void divide(int x)
{
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0)
{
int s = 0;
while (x % i == 0) x /= i, s ++ ;
cout << i << ' ' << s << endl;
}
if (x > 1) cout << x << ' ' << 1 << endl;
cout << endl;
}
3.筛质数
1.埃氏筛
int primes[N], cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (st[i]) continue;
primes[cnt ++ ] = i;
for (int j = i + i; j <= n; j += i)
st[j] = true;
}
}
2.线性筛
int primes[N], cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (!st[i]) primes[cnt ++ ] = i;
for (int j = 0; primes[j] <= n / i; j ++ )
{
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
快速求出n!的质因数的个数 - Slager_Z - 博客园 (cnblogs.com)
https://www.cnblogs.com/Slager-Z/p/7780382.html
二、约数
1.试除法求约数
vector<int> get_divisors(int x)
{
vector<int> res;
for (int i = 1; i <= x / i; i ++ )
if (x % i == 0)
{
res.push_back(i);
if (i != x / i) res.push_back(x / i);
}
sort(res.begin(), res.end());
return res;
}
2.约数个数与约数之和
如果 N = p1^c1 * p2^c2 * ... *pk^ck
约数个数: (c1 + 1) * (c2 + 1) * ... * (ck + 1)
约数之和: (p1^0 + p1^1 + ... + p1^c1) * ... * (pk^0 + pk^1 + ... + pk^ck)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
int main(){
int n,x;
LL ans = 1;
unordered_map<int,int> hash;
cin >> n;
while(n--){
cin >> x;
for(int i = 2;i <= x/i; ++i){
while(x % i == 0){
x /= i;
hash[i] ++;
}
}
if(x > 1) hash[x] ++;
}
for(auto i : hash) ans = ans*(i.second + 1) % mod;
cout << ans;
return 0;
}
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 110, mod = 1e9 + 7;
int main()
{
int n;
cin >> n;
unordered_map<int, int> primes;
while (n -- )
{
int x;
cin >> x;
for (int i = 2; i <= x / i; i ++ )
while (x % i == 0)
{
x /= i;
primes[i] ++ ;
}
if (x > 1) primes[x] ++ ;
}
LL res = 1;
for (auto p : primes)
{
LL a = p.first, b = p.second;
LL t = 1;
while (b -- ) t = (t * a + 1) % mod;
res = res * t % mod;
}
cout << res << endl;
return 0;
}
其中,unordered_map<int,int> hash;
首先unordered_map是哈希表,该题数据量太大,而哈希表恰好可以提高访问单个数据的效率。同时unordered_map是可以存放pair类型的数据,它的first存储的是质数,他的second存储的是个数,遍历时速度会更快
其次,这里需要注意代码中是ans=ans*……,不能写成*=,不然数据会溢出。
// 模运算与基本四则运算有些相似,但是除法例外。其规则如下:
// (a + b) % p = (a % p + b % p) % p (1)
// (a - b) % p = (a % p - b % p ) % p (2)
// (a * b) % p = (a % p * b % p) % p (3)
// a ^ b % p = ((a % p)^b) % p (4)最后,注意for(auto i:hash)的使用
3.欧几里得算法求最大公约数
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
三、欧拉函数
1.求欧拉函数
int phi(int x)
{
int res = x;
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0)
{
res = res / i * (i - 1);
while (x % i == 0) x /= i;
}
if (x > 1) res = res / x * (x - 1);
return res;
}
对于正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目,记作φ(n).φ(1)=1。
2.筛法求欧拉函数
int primes[N], cnt; // primes[]存储所有素数
int euler[N]; // 存储每个数的欧拉函数
bool st[N]; // st[x]存储x是否被筛掉
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;
}
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);
}
}
}
四、快速幂
1.快速幂
位运算-取整数n的二进制数第k位数 - AcWinghttps://www.acwing.com/blog/content/2647/
#include<iostream>
using namespace std;
long long qmi(long long a,int b,int p)
{
long long res=1;
while(b)//对b进行二进制化,从低位到高位
{
//如果b的二进制表示的第0位为1,则乘上当前的a
if(b&1) res = res *a %p;
//b右移一位
b>>=1;
//更新a,a依次为a^{2^0},a^{2^1},a^{2^2},....,a^{2^logb}
a=a*a%p;
}
return res;
}
int main()
{
int n;
cin>>n;
while(n--)
{
cin.tie(0);
ios::sync_with_stdio(false);
int a,b,p;
long long res=1;
cin>>a>>b>>p;
res = qmi(a,b,p);
cout<<res<<endl;
}
return 0;
}
2.快速幂求逆元
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL qmi(int a, int b, int p)
{
LL res = 1;
while (b)
{
if (b & 1) res = res * a % p;
a = a * (LL)a % p;
b >>= 1;
}
return res;
}
int main()
{
int n;
scanf("%d", &n);
while (n -- )
{
int a, p;
scanf("%d%d", &a, &p);
if (a % p == 0) puts("impossible");
else printf("%lld\n", qmi(a, p - 2, p));
}
return 0;
}
分析过程可见欧拉定理与费马定理 。