蓝桥杯java算法学习(六)

注意:以下部分内容摘自Acwing,仅用于个人学习记录,不做任何商业用途。

一、质数

(1)试除法判定质数

重点在 i 的循环终止条件:i  <=  n / i ,一定是小于等于 <= !!!
此外,必须判断n是否小于2

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)筛质法

线性筛质法:(没看懂mad)

参考链接:AcWing 868. 对于——筛质数——三种方法的解释 - AcWing

void get_primes(){
    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;
        }
    }
}

二、约数

(1)试除法求约数

主要是注意list如何排序 的问题(记得去重)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
public class Main {
	static void divisors(int x) {
		ArrayList<Integer> list=new ArrayList<>();	
		for(int i=1;i<=x/i;i++) {
			 if(x % i == 0){
			list.add(i);
			if(x / i != i)list.add(x / i);
			 }
		}
		Collections.sort(list, (a, b)->a - b);
		int r=-1;
		for(int c : list){
			if(r!=c)
            System.out.print(c + " ");
			r=c;
        }
        System.out.println();
	}
	public static void main(String[] args) throws IOException {
	   BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
	   int n=Integer.parseInt(br.readLine());
	   for (int i=0;i<n;i++) {
		   int x=Integer.parseInt(br.readLine());
		   divisors(x);
	   }
	   
	}
}

(2)求约数个数

所以先用一中的方法求出质数及其个数,再相乘。

(3)约数之和

(4)最大公约数 

辗转相除法

        cin >> a >> b;
        //辗转相除,直到小括号内右边数为0
        while(b)
        {
            //c 一定小于 b
            int c = a % b;
            //小括号左边放除数,右边放约数
            a = b;
            b = c;
        }
        //小括号内左边数为最大公约数
        cout << a << endl;

三、欧拉函数

欧拉函数的定义:

        cin>>a;
        res = a;
        for(int i=2;i<=a/i;i++)
        {
            if(a%i==0)
            {
                while(a%i==0)
                    a/=i;
                res = res / i*(i-1);
            }
        }
        if(a>1) res = res /a*(a-1);
        cout<<res<<endl;

优化:

void get_eulers(int n)
{
    phi[1] = 1;
    for (int i = 2; i <= n; i++)
    {
        if (!st[i])
        {
            primes[cnt++] = i;
            phi[i] = i - 1; 
        }
        for (int j = 0; primes[j] <= n / i; j++)
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0)
            {
                phi[primes[j] * i] = phi[i] * primes[j]; 
                break;
            }
            phi[primes[j] * i] = phi[i] * (primes[j] - 1);
        }
    }
}

作者:番茄酱
链接:https://www.acwing.com/solution/content/3952/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

四、快速幂

快速幂:快速求a^b% p的问题,时间复杂度:O(logb),若对于n组数据,那么时间复杂度为O(n∗logb)

思路: 

 五、扩展欧几里得算法

详见:AcWing 877. 扩展欧几里得算法 - AcWing

题目:

六、组合数 

(1)公式法求组合数

(2)费马小定理

AcWing 886. 费马小定理, 快速冥, 求组合数 II - AcWing


import java.io.*;
class Main{
    static BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
    static int N = 100010, p = (int) 1e9 + 7;
    static int[] fact = new int[N], infact = new int[N];

    public static int qmi(int a, int k, int p){
        long res = 1;
        while( k > 0){
            if( (k & 1) != 0 ) res = res * a % p;
            a =(int) ((long) a * a % p);
            k >>= 1;
        }
        return (int) res;
    }

    public static void main(String[] args) throws Exception{
        int t = Integer.valueOf(read.readLine());
        fact[0] = infact[0] = 1;
        for(int i = 1; i < N; i++){
            fact[i] =(int) ((long)fact[i - 1] * i % p);
            infact[i] = (int) ((long) infact[i - 1] * qmi(i, p - 2, p ) % p);
        }

        while(t -- > 0){
            String[] ss = read.readLine().split(" ");
            int a = Integer.valueOf(ss[0]);
            int b = Integer.valueOf(ss[1]);
            int res = (int) ((long) fact[a] * infact[a - b] % p * infact[b] % p);
            System.out.println(res);
        }
    }

}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值