质数,约数,欧拉函数,这不是小学的知识吗,至于搁这总结吗?刷过一点蓝桥杯的题告诉你,非常至于,如果你只会简单的不会优化的算法,你会发现你提交的结果都是tle的,下面我就来总结一下蓝桥杯常考的数论知识,每一个知识后面都会附上蓝桥杯的真题哦!
1.质数,分解质因数
1.你没有忘了质数的定义吧铁铁,质数是指只包含一和它本身两个约数的数,代码很简单,如下:
bool is_prime(int n){
if(n < 2) return false;
for(int i = 2;i < n;i ++){
if(n % i == 0){
return false;
}
}
return true; //返回是
}
但是这样就完了吗,很显然当时不懂算法的大一的我只能写出这样的代码,不懂什么优化。了解了一点算法就会发现这个优化其实很简单,如果i可以整除n,那么n/i也一定能整除n,这样我们只需要枚举较小的因子就可以了,时间复杂度从O(n)优化到了O(sqrt(n));看一下代码
bool is_prime(int n){
if(n < 2) return false;
for(int i = 2;i <= n / i;i ++){ //优化内容
if(n % 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;
}
n最多只包含一个大于根号n的质因子,利用这个性质,就可以将复杂度降到根号n啦! 写了有一会了,我们来干一些刺激的事情,直接给我上真题!
怎么样,是不是很简单,在蓝桥杯考试遇到那天你就乐吧!
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
long n = sc.nextLong();
long res=0;
for (long i = 2; i <=n/i ; i++) {
if(n%i==0){
while(n%i==0){
n/=i;
}
res++;
}
}
if(n>1) res++;
System.out.println(res);
}
这道题在官网上的标签竟然是中等,啊?
2.埃氏筛素数
筛选素数有三种方法,朴素筛,埃氏筛法,线性筛法。
虽然线性筛是性能最好的,但是在蓝桥杯中埃氏筛法就够用了,而且好理解!!!
void get_primes1(){
for(int i=2;i<=n;i++){
if(!st[i]){
primes[cnt++]=i;
for(int j=i;j<=n;j+=i) st[j]=true;//可以用质数就把所有的合数都筛掉;
}
}
}
3.最大公因数,最小公倍数
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
4.快速幂
求 m^k mod p,时间复杂度 O(logk)。
int qmi(int m, int k, int p)
{
int res = 1 % p, t = m;
while (k)
{
if (k&1) res = res * t % p;
t = t * t % p;
k >>= 1;
}
return res;
}
省赛最常考的一般就这些了,好好掌握吧!!!