【算法基础16】欧拉全家桶(欧拉函数与欧拉定理、费马小定理、快速幂)

一、欧拉函数

        1.欧拉函数的定义

        

       

         2.求一个数的欧拉函数

int get_euler(int a){
	int res=a;
	
	for(int i=2;i<=a/i;i++){
		if(a%i==0){//试除法找质因子
			res=res/i*(i-1);
			while(a%i==0) a/=i;
		}
	}
	if(a>1) res=res/a*(a-1);//大于a/i的质因子
	
	return res;
}

        3.求小于n的欧拉函数之和

int sum_eulers(int n){
	phi[1]=1;//数组phi存欧拉函数值

	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){//primes[j]不是primes[j]*i的质因子
                //质因子相同,N部分乘primes[j]
				phi[primes[j]*i]=phi[i]*primes[j];
				break;
			}
            //质因子部分除以primes[j],N部分乘primes[j],二者抵消了
			phi[primes[j]*i]=phi[i]*(primes[j]-1);            
		}
	}
	long long int res=0;
	for(int i=1;i<=n;i++) res+=phi[i];//求和
	
	return res;
}

二、欧拉定理与费马小定理

        1.欧拉定理

        若a与n互质,则a^{\phi _{\left ( n \right )}}\equiv 1 (mod n)。例:当a=5,n=6时,由于6的欧拉函数为2,则25与1对于模6相等。

        2.费马小定理

        若p是一个质数,a为不是p的倍数的整数,则 a^{p-1}\equiv 1 (mod p)。

三、快速幂

        主要思想:在O(logk)内求出a^{k}mod p。先预处理计算出logk个值:a^{2^{0}}mod k,a^{2^{1}}mod k...a^{2^{logk}} mod k,a^{k}可以这些值的乘积表示。由底数相同的数相乘即把指数相加,可以把k拆解成2^{0}2^{logk}的和,即相当于用二进制表示k,当k的二进制表示在第i位为1时,就将答案乘以a^{2^{i}}mod p。

        例题:给出三个数a,k,p,求a^{k}mod p。

int qmi(int a,int k,int p){
	int res=1;

	while(k){
		if(k&1) res=res*a%p;//k的最低位为1,乘以第i个预处理数
		k>>=1;//k右移一位
		a=a*a%p;//由第i个预处理数求第i+1个预处理数
	}

	return res;
}

 

        应用:求一个数的乘法逆元。由乘法逆元的定义以及费马小定理可以得,求一个数a的乘法逆元即为求a^{k-2}mod p,代入快速幂公式。

                                 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于欧拉定理与贪心算法的钢板最优切割路径问题的MATLAB代码如下: ```matlab function [path] = steelCutting(width, height, cuts % 初始化钢板 board = zeros(height, width); % 记录切割路径 path = []; % 对每一次切割进行贪心选择 for i = 1:cuts % 计算当前钢板的欧拉数 euler = calculateEuler(board); % 寻找最优切割位置 bestScore = -Inf; bestPos = []; % 遍历每个位置进行切割 for y = 1:height-1 for x = 1:width-1 % 判断当前位置是否可切割 if board(y,x) == 0 && board(y+1,x) == 0 && board(y,x+1) == 0 && board(y+1,x+1) == 0 % 切割后的钢板 newBoard = board; newBoard(y,x) = 1; newBoard(y+1,x) = 1; newBoard(y,x+1) = 1; newBoard(y+1,x+1) = 1; % 计算切割后的欧拉数 newEuler = calculateEuler(newBoard); % 计算得分 score = euler - newEuler; % 更新最优得分和位置 if score > bestScore bestScore = score; bestPos = [x, y]; end end end end % 更新切割路径和钢板 path = [path; bestPos]; board(bestPos(2),bestPos(1)) = 1; board(bestPos(2)+1,bestPos(1)) = 1; board(bestPos(2),bestPos(1)+1) = 1; board(bestPos(2)+1,bestPos(1)+1) = 1; end % 绘制切割路径图像 figure; imagesc(board); colormap(gray); hold on; plot(path(:,1)+0.5, path(:,2)+0.5, 'r-', 'LineWidth', 2); hold off; end function [euler] = calculateEuler(board) % 计算钢板的欧拉数 euler = sum(sum(board)) - sum(sum(board(2:end,2:end))); end ``` 使用方法: ```matlab width = 10; % 钢板宽度 height = 8; % 钢板高度 cuts = 5; % 切割次数 path = steelCutting(width, height, cuts); ``` 这段代码实现了基于欧拉定理与贪心算法的钢板最优切割路径问题,并输出了切割路径的图像。在代码中,首先定义了一个`steelCutting`函数,该函数接受钢板的宽度、高度和切割次数作为输入参数。然后,通过贪心算法选择最优切割位置,并记录切割路径。最后,绘制钢板和切割路径的图像。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值