快速取模运算

转载自http://blog.sina.com.cn/s/blog_8619a25801010wcy.html

转载自http://blog.sina.com.cn/s/blog_8619a25801010wcy.html

mathematics对于程序是很重要的,光会bruteforce是不能提高编程水平的,最近做的上机题目尤其是上交跟清华北大都用到不少相关的东西,巧妙的解决了问题。 
        从本篇开始对于一些用到的数学知识进行总结。 

------------之一:快速幂取模 
       计算x^ymod n;如果采用常规方法,当x与y都比较小的情况下,采用直接计算可以,但是如果当x跟y都非常大的时候,如2^1000mod 100000,那该如何解决呢? 
      利用模运算的这个:(a*b)mod n = ((a mod n) * b ) mod n; 
      例如:2^11 mod 100 = 2^(1011) mod 100= ((2 ^(1010)mod 100)*2)mod 100…… 
       1011为11的二进制表示 
      于是就有如下的实现过程了:

  1. #define LL long long int
  2. LL exp_mod( LL x , LL y , LL n ){
  3.      LL ret=1;
  4.      while(y){
  5.              if(y&1) ret=(ret*x)%n;
  6.              x=(x*x)%n;
  7.              y=y>>1;
  8.      }
  9.      return ret;
  10. }

    程序执行次数至于y的位长度有关。

    实战例子:求root(N, k)

        2010年清华的上机题目,题意请点击题目处链接。

        本题可以有如下分析:

       N=a0+a1*k+a2*k^2+……+an*k^n;

       N'=a0+a1+a2+……+an;

       N-N'=a1*(k-1)+a2*(k^2-1)+……+an*(k^n-1);

       提取(k-1)有: (N-N')%(K-1)=0;

       继续递推下去有: (N-N')%(k-1) =0;

                                    (N'-N'')%(k-1)=0;

                                      ……

                                     (N(r-1)-N(r))%(k-1)=0;

        相加有:(N-N(r))%(k-1)=0,N(r)是我们要求的结果,故有

        N(r) = N % (k-1);

        如果 N(r)==0 ,为边界,则 N(r) = k-1;

         至于如何取模运算参考上面刚学习的快速幂取模即可。

        实现代码如下:

  1. #include <stdio.h>
  2. #define LL long long int
  3. LL exp_mod(LL x,LL y,LL n){
  4.     LL ret=1;
  5.     while(y){
  6.         if(y&1) ret=(ret*x)%n;
  7.         x=(x*x)%n;
  8.         y=y>>1;   
  9.     }   
  10.     return ret;
  11. }
  12.  
  13. int main(){
  14.     LL a,b,k,ans;
  15.      
  16.     while(scanf("%lld%lld%lld",&a,&b,&k)==3){
  17.         ans=exp_mod(a,b,k-1);
  18.         if(ans==0) ans=k-1;
  19.         printf("%lld\n",ans);  
  20.     }
  21.     return 0;
  22. }

-----------Amazing Mathematics



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值