试除法判定质数
#include<iostream>
using namespace std;
const int maxn=111;
int n;
bool isPrime(int x)
{
if(x<2) //注意x<2为return false
return false;
for(int i=2; i<=x/i; i++) //i<=x/i
if(x%i==0)
return false;
return true;
}
int main()
{
cin >> n;
for(int i=0; i<n; i++)
{
int temp;
cin >> temp;
if(isPrime(temp))
cout << "Yes" << endl;
else
cout << "No" << endl;
}
return 0;
}
分解质因数
#include<iostream>
using namespace std;
const int maxn=111;
int n;
int divide(int x)
{
for(int i=2; i<=x/i; i++) //从2开始遍历数字
if(x%i==0) //如果x能求余i为0
{
int s=0; //s统计i的个数
while(x%i==0)
{
x/=i;
s++;
}
cout << i << " " << s << endl;
}
//下面这个if不是在上面那个for中的
if(x>1) //如果此时x>1,表示剩下最后一个素数
cout << x << " " << 1 << endl;
cout << endl;
}
int main()
{
cin >> n;
for(int i=0; i<n; i++)
{
int x;
cin >> x; //输入要找的数字
divide(x);
}
return 0;
}
晒素数
#include <iostream>
#include <algorithm>
using namespace std;
const int N= 1000010;
int primes[N], cnt;
bool st[N];
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ ) //i从2开始一直到n枚举
{
if (!st[i]) primes[cnt ++ ] = i; //如果i为素数,则将i统计到primes中
for (int j = 0; primes[j] <= n / i; j ++ ) //从小到大枚举所有的素数
{
st[primes[j] * i] = true; //这个一定是存在的
if (i % primes[j] == 0) break; //如果i%primes[j]==0,表示primes[j]一定是i的最小素数
}
}
}
int main()
{
int n;
cin >> n; //输入n,统计1——n的所有质数的个数
get_primes(n);
cout << cnt << endl;
return 0;
}
试除法求约数
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=111;
int n;
vector<int> kkk(int x)
{
vector<int> res;
for(int i=1; i<=x/i; i++)
if(x%i==0) //只要能让x%i==0,表示i就是x的约数
{
res.push_back(i);
if(i!=x/i)
res.push_back(x/i);
}
sort(res.begin(),res.end());
return res;
}
int main()
{
cin >> n;
for(int i=0; i<n; i++)
{
int temp;
cin >> temp;
auto res=kkk(temp);
for(auto item:res)
cout << item << " ";
cout << endl;
}
return 0;
}
约数个数
#include<iostream>
#include<unordered_map>
using namespace std;
const int maxn=111;
const int mod=1e9+7;
int n;
int main()
{
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]++; //注意这个数字是自增的,有可能是x会相同,所以还是要自增
}
long long res=1; //res的值很大,所以设置为long long
for(auto item:primes)
res=res*(item.second+1)%mod;
cout << res;
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;
//需要这道题算出96的所有约数之和
int main()
{
int n;
cin >> n; //输入n
unordered_map<int, int> primes; //设置primes
while (n -- )
{
int x;
cin >> x; //输入x
for (int i = 2; i <= x / i; i ++ ) //统计x的所有素数的个数
while (x % i == 0)
{
x /= i;
primes[i] ++ ;
}
if (x > 1) primes[x] ++ ;
}
LL res = 1;
for (auto p : primes) //用p去遍历primes
{
LL a = p.first, b = p.second; //a是底数,b是指数
LL t = 1; //t表示为1
while (b -- ) //这就是那个计算方法
t = (t * a + 1) % mod;
res = res * t % mod;
}
cout << res << endl;
return 0;
}
欧拉函数
与n互质的数
#include <iostream>
using namespace std;
int phi(int x)
{
int res = x;
for (int i = 2; i <= x / i; i ++ ) //这相当于在找x的所有因数
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;
}
int main()
{
int n;
cin >> n; //输入n
while (n -- )
{
int x;
cin >> x; //输入x
cout << phi(x) << endl;
}
return 0;
}
筛法求欧拉函数
#include <iostream>
#include <algorithm>
//两个数字互质,表示两个数没有相同的质因子
using namespace std;
typedef long long LL;
const int N = 1000010;
int primes[N], cnt; //primes存放的是每个素数,cnt是其下标
int phi[N]; //phi表示每个数的欧拉函数
bool st[N];
void get_eulers(int n)
{
phi[1] = 1; //1的欧拉函数只有1个
for (int i = 2; i <= n; i++)
{
if (!st[i])
{
primes[cnt++] = i;
phi[i] = i - 1; //如果i是一个质数的话,从1--i中一共有i-1个数字与i互质,则ph[i]=i-1
}
for (int j = 0; primes[j] <= n / i; j++) //从小到大枚举每个素数
{
st[primes[j] * i] = true;
if (i % primes[j] == 0) //说明pj是i的质因子
{
phi[primes[j] * i] = phi[i] * primes[j];
break;
}
phi[primes[j] * i] = phi[i] * (primes[j] - 1); //i%primes[j]不为0
}
}
}
int main()
{
int n;
cin >> n;
get_eulers(n);
LL res = 0;
for (int i = 1; i <= n; i++) res += phi[i];
printf("%lld\n", res);
return 0;
}
快速幂
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL qmi(int a, int b, int p) //a^b%p的结果
{
LL res = 1; //返回的是res为long long类型
while (b) //本质上求的是b的二进制结果,当b不为0时
{
if (b & 1) res = res * a % p; //b&1就是判断b的二进制表示中第0位上的数是否为1,若为1,b&1=true,反之b&1=false
a = (LL) a *a % p; //b&1也可以用来判断奇数和偶数,b&1=true时为奇数,反之b&1=false时为偶数
b = b >> 1; //左移1位,相当于除以2
} //注意由于res为long long类型,而且上面res=rea*a,res为longlong类型,所以要修改a的值
return res;
}
int main()
{
int n;
scanf("%d", &n); //输入n的值
while (n -- ) //n递减
{
int a, b, p;
scanf("%d%d%d", &a, &b, &p);
printf("%lld\n", qmi(a, b, p)); //注意结果是long long类型
}
return 0;
}
快速幂求逆元
#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;
}
扩展的欧几里得算法
#include <iostream>
#include <algorithm>
using namespace std;
int exgcd(int a, int b, int &x, int &y)
{
if (!b) //如果b为0,比如 8 0,则最大公约数为8,则x为1,y为0
{
x = 1, y = 0;
return a; //返回a
}
//如果b不为0
int d = exgcd(b, a % b, y, x); //
y = y- a / b * x;
return d;
}
int main()
{
int n;
scanf("%d", &n);
while (n -- )
{
int a, b;
scanf("%d%d", &a, &b); //输入a,b
int x, y; //设置x,y
exgcd(a, b, x, y); //传入a,b,x,y
printf("%d %d\n", x, y); //直接输出x,y
}
return 0;
}
线性同余方程
求一个数x,使a*x/m的余数是b
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
int exgcd(int a, int b, int &x, int &y)
{
if (!b)
{
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y = y - a / b * x;
return d;
}
int main()
{
int n;
scanf("%d", &n); //输入n
while (n -- ) //n的值递减
{
int a, b, m; //我们要找到一个x,使得a*x%m==b
scanf("%d%d%d", &a, &b, &m);
int x, y;
int d = exgcd(a, m, x, y); //这个d,表示a,m的最大公约数
if (b % d) puts("impossible");
else printf("%d\n", (LL)b / d * x % m); //求余m表示在m的范围内
}
return 0;
}