最近都在讲一些数论,主要研究整数的性质,有非常多的结论以及推论和证明,涉及很广,但这些都是方法,就是有时就能突然用到,可以加快运行的速度
1.埃氏筛法-求1-n的素数
它就是把素数的倍数给筛选掉,不用再去判断
把范围内的数给状态true。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f3f;
typedef long long ll;
#define maxn 1000000
bool isPrime[maxn + 1];
void eratos(int n)
{
int i, j;
isPrime[0] = isPrime[1] = false;
for (i = 2; i <= n; ++i)
isPrime[i] = true;
for (i = 2; i * i <= n; ++i)
if (isPrime[i])
{
for (j = i * i; j <= n; j += i)
isPrime[j] = false;
}
}
int main()
{
int n; cin >> n;
eratos(n);
for (int i = 0; i <= n; i++)
{
if (isPrime[i] != 0)
cout << i << " ";
}
}
2.求因数和
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f3f;
typedef long long ll;
int main()
{
int t; cin >> t;
while (t--)
{
int n; cin >> n;
ll s = 1;
for (int i = 2; i*i<=n; i++)
{
if (n % i == 0)
{
s += i;
if (n/i != i)
s +=n/i;
}
}
cout << s << endl;
}
}
3.最大公约数gcd和最小公倍数lcm
性质:gcd(a,b)=gcd(a,ka+b)
最小公倍数 = 两数的乘积 / 最大公约数
①求最大公约数的:辗转相除法
int f(int m, int n)
{
if (m%n == 0) return n;
else
{
return f(n,m%n);
}
}
int main()
{
int m, n, t; cin >> m >> n;
if (m == n)
{
cout << m; return 0;
}
if (m > n) cout << f(m, n);
if (m < n) cout << f(n, m);
}
②最小公倍数
最小公倍数 = 两数的乘积 / 最大公约数
int f(int m, int n)
{
if (m%n == 0) return n;
else
{
return f(n,m%n);
}
}
int main()
{
int m, n; int t;
while (cin >> m >> n)
{
if (m == n)
{
t=m;
}
if (m > n) t=f(m, n);
if (m < n) t=f(n, m);
cout << endl;
cout << "最小公倍数:" << m * n / t << endl;
}
}
4.模的性质
1.a%p结果一定在[0,p-1]的范围内。
2.(a+b)%m=(a%m+b%m)%m;
3.(a-b)%m=((a%m-b%m)+m)%m;
4.(ab)%m=(a%mb%m)%m;
如果a%m=b%m,那么 记做:a≡b(%m)-----同余
5.幂取模
计算(a^n)%m的值
快速幂的方法:
int gg(int a,int n,int m){
if(n == 0) return 1;
int x = gg(a,n/2,m);
long long ans = (long long)x * x % m;
if(n % 2 == 1) ans = ans * a % m;
return ans;
}
快速幂
ll pow(ll a,ll m,ll mod)分别是底数,幂,模
{
int res = 1;
while(m){
if(m&1){
res=res*a%mod;
}
a=a*a%mod;
m>>=1;
}
return res;
}
6.
1.费马小定理:若p为素数,且a和p互素,那么a^(p-1)≡1(mod p)
其实费马小定理主要用于求乘法逆元,如果a, p互质且p为质数,则a^(p-2)就是a关于mod p的乘法逆元
2.欧拉定理:在p不是素数的时候,对于和m互素的a,有:a^(f(m))≡1(mod m);
3.裴蜀定理:对于任何a,b 关于未知数x y的线性不定方程
ax+by=c;
当 a,b互素等价于ax+by=1有解
7.唯一分解定理
任何一个大于1的自然数n,都可以唯一分解成有限个质数的乘积
n=pr11∗pr22∗…∗prkk
p1<p2<…<pk均为质数,r1,r2,…rk均为正整数
for(int i=2;i<=sqrt(n);i++)
{
while(n%i==0)
prime[i]++,n/=i;
}
8.
12>>1 等价于 12/2 ;>>后面跟着几 就除几次2
总结:在做数论的题目时候就很容易发现,这些题目直接做 或者是直接想按照题目的指引去做 代码很好写,问题就是在时间上,非常非常非常非常非常非常非常非常非常容易超时,所以学习数论就是一方面能够简化代码 同时还能加快运算速度,AC更容易;还有这类题目都用到非常多的结论,尽量记下来,用的时候确实很方便,还有很多的题目,都是有一些隐藏的规律就是通过试样例,就能发现一些规律。