为你写诗

c/c++
随笔 - 32, 文章 - 0, 评论 - 3, 引用 - 0
数据加载中……

快速幂

原文:http://hi.baidu.com/fenglehuo/blog/item/3ce1f7b4a0ffd67e8bd4b2d8.html
求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 
利用这一点,我们可以递推地算出所有的a^(2^i) 
当然由算法1的结论,我们加上取模运算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; 
}

例题

D: Raising Modulo Numbers


Time Limit: 1000 ms     Case Time Limit: 1000 ms     Memory Limit: 30000 KB
Submit: 24     Accepted: 7 

Description

People 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 the KOKODá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 AiBi 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.

Input

The 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.

Output

For each assingnement there is the only one line of output. On this line, there is a number, the result of expression

(A1B1+A2B2+ ... +AHBH)mod M.

Sample Input

3 16 4 2 3 3 4 4 5 5 6 36123 1 2374859 3029382 17 1 3 18132

Sample Output

2
13195
13

题意

给出A1~Ah,B1~Bh,M,H,求(A1B1+A2B2+ ... +AHBH)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;
}

posted on 2011-06-10 23:12 pp_zhang 阅读(337) 评论(0)  编辑 收藏 引用 所属分类: 数论


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理