当前位置:文档之家› RSA加密(快速幂求余)

RSA加密(快速幂求余)

快速幂求余算法(OJ T1128)求a^b%c(这就是著名的RSA公钥的加密方法)当a,b很大时,直接求解这个问题不太可能,你能想到哪些优化呢?算法1:直观上,也许最容易想到的是利用a*b%c=((a%c)*b)%c,这样每一步都进行这种处理,这就解决了a^b可能太大存不下的问题,但这个算法的时间复杂度依然是O(n),根本没有得到优化。

当b很大时运行时间会很长算法2:另一种算法利用了分治的思想,可以达到O(logn)。

可以把b按二进制展开为b=p(n)*2^n+p(n-1)*2^(n-1)+...+p(1)*2+p(0)其中p(i) (0<=i<=n)为0或1这样a^b=a^(p(n)*2^n+p(n-1)*2^(n-1)+...+p(1)*2+p(0)) =a^(p(n)*2^n)*a^(p(n-1)*2^(n-1)*...*a^(p(1)*2)*a^p(0)对于p(i)=0的情况,a^p(i)*2^(i-1)=a^0=1,不用处理,我们要考虑的仅仅是p(i)=1的情况,a^(2^i)=(a^(p(i)*2(i-1)))^2 (当p(i)=1时,a^(2^i)=(a^(2(i-1)))^2)利用这一点,我们可以递推地算出所有的a^(2^i)当然由算法1的结论a*b%c=((a%c)*b)%c,我们加上取模运算a^(2^i)%c=((a^(2(i-1))%c)*a^(2(i-1)))%c 于是再把所有满足p(i)=1的a^(2^i)%c按照算法1乘起来再%c就是结果示例:3^6%7=3^(2^2)*3^(2^1)%7=((3^(2^1))^2%7)*(3^1*3^1%7)=(((3^1*3^1%7)%7)^2%7*2%7)%7=(4*2)%7=8%7=1当然算法可以进一步改进,比如二进制的每一位不必存起来,可以边求边用经改进后代码如下:(输入a,k,m,求a^k%m)long f(long a,long k,long m){long b=1;while(k>=1){if(k%2==1) b=a*b%m;a=a*a%m;k=k/2;}return b;}例题一、高级机密Time Limit:1000MS Memory Limit:65536KTotal Submit:43 Accepted:16Description在很多情况下,我们需要对信息进行加密。

特别是随着Internet的飞速发展,加密技术就显得尤为重要。

很早以前,罗马人为了在战争中传递信息,频繁地使用替换法进行信息加密。

然而在计算机技术高速发展的今天,这种替换法显得不堪一击。

因此研究人员正在试图寻找一种易于编码、但不易于解码的编码规则。

目前比较流行的编码规则称为RSA,是由美国麻省理工学院的三位教授发明的。

这种编码规则是基于一种求幂取模算法的:对于给出的三个正整数a,b,c,计算a的b次方除以c的余数。

你的任务是编写一个程序,计算a b mod c。

Input输入数据只有一行,依次为三个正整数a,b,c,三个正整数之间各以一个空格隔开,并且1<=a,b < c < =32768。

Output输出只有一个整数表示计算结果。

Sample Input2 6 11Sample Output9解:import ;//对于给出的三个正整数a,b,c,计算a的b次方除以c的余数,即:a^b mod c //相关公式:用二进制表示b:b=p(n)*2^n+p(n-1)*2^(n-1)+...+p(1)*2+p(0) (其中p(i)值为0或1)//则a^b=a^(p(n)*2^n+p(n-1)*2^(n-1)+...+p(1)*2+p(0))//=a^(p(n)*2^n)*a^(p(n-1)*2^(n-1))*...*a^(p(1)*2)*a^p(0) public class TopSecret {public static void main(String[] args) { long a,b,c;Scanner input=new Scanner(System.in);a=input.nextInt();b=input.nextInt();c=input.nextInt();,b,c));}public static long getPowMod(long a,long b,long c){long result=1;while(b>=1){if(b%2==1) result=a*result%c;a=a*a%c;b/=2; //通过b/2来求得p(i)为1还是0}return result;}}二、D: Raising Modulo NumbersTime Limit: 1000 ms Case Time Limit: 1000ms Memory Limit: 30000 KBSubmit: 24 Accepted: 7DescriptionPeople are different. Some secretly read magazines full of interesting girls' pictures, others create an A-bomb in their cellar, others like using Windows, and some like difficult mathematical games. Latest marketing research shows, that this market segment was so far underestimated and that there is lack of such games. This kind of game was thus included into theKOKODáKH. The rules follow:Each player chooses two numbers Ai and Bi and writes them on a slip of paper. Others cannot see the numbers. In a given moment all players show their numbers to the others. The goal is to determine the sum of all expressions Ai Bi from all players including oneself and determine the remainder after division by a given number M. The winner is the one who first determines the correct result. According to the players' experience it is possible to increase the difficulty by choosing higher numbers.You should write a program that calculates the result and is able to find out who won the game.InputThe input consists of Z assignments. The number of them is given by the single positive integer Z appearing on the first line of input. Then the assignements follow. Each assignement begins with line containing an integer M (1 <= M <= 45000). The sum will be divided by this number. Next line contains number of players H (1 <= H <= 45000). Next exactly H lines follow. On each line, there are exactly two numbers Ai and Bi separated by space. Both numbers cannot be equal zero at the same time.OutputFor each assingnement there is the only one line of output. On this line, there is a number, the result of expression(A1B1+A2B2+ ... +A H B H)mod M.Sample Input31642 33 44 55 63612312374859 30293821713 18132Sample Output21319513题意给出A1~Ah,B1~Bh,M,H,求(A1B1+A2B2+ ... +A H B H)mod M.做法快速幂取模+累加步步取模HIT取模相当于在原数中不断减去M直到原数小于M,所以累加后取模和步步取模结果相同,因此在累加过程中取模以防止超过long long界限CODE#include <stdio.h>long long z,h,a,b,m,ans,pow;int main(){scanf("%I64d",&z);while(z--){scanf("%I64d %I64d",&m,&h);ans=0;while(h--){scanf("%I64d %I64d",&a,&b);pow=1;while(b>=1){if(b%2==1)pow=a*pow%m;a=a*a%m;b/=2;}ans+=pow;ans%=m;}printf("%I64d\n",ans);}return 0; }。

相关主题