大数取余

加法取余:

(a+b) % c = (a%c + b%c) % c

 

减法取余:

(a-b) % c = (a-b+c) % c

 

乘法取余:

法1:

       (a*b) % c = [(a%c) * (b%c)] % c     (前提:c*c不会溢出)

法2:

       b = 2^(n) + … + 2^(i) + …            //将b用二进制形式表示

       (a*b) % c = [a * (2^(n) + … + 2^(i) + …)] % c = [(a*(2^n)) + …… + (a*2(i)) + ……] %c  =  [(a*(2^n))%c  + …… + (a*2(i))%c  + ……] %c 

 

//二进制转换为10进制可以以2的权值相加(貌似是这样描述的)。比如13=(1101)2=1*2^3+1*2^2+0*2^1+1*2^0。
//同样的,当我们计算A*B的时候,也可以将B化成2^n相加的式子。
//于是,我们可以将a*b mod c转换成[a*(2^b0+2^b1+……2^bn)] mod c=[a*2^b0+a*2^b1+……a*2^bn] mod c。
//利用公式(a+b)mod c=[(a mod c)+(b mod c)]mod c这个公式进行运算。

__int64 mult_mod(__int64 a,__int64 b,__int64 c)
{    
	a%=c;    
	b%=c;    
	__int64 ret=0;//ret记录最终的结果    
	while(b)//判断不是不是为0了    
	{        
		if(b&1)//如果b的二进制中的最后一位为1 那么加上a
		{
			ret+=a;ret%=c;
		}        
		a<<=1;
		a%=c;//a随着b中二进制位数而扩大每次扩大两倍。        
		b>>=1;//b来缩小两倍 去掉最后一位 因为当前最后一位我们用完了,    
	}    
	return ret;
}

 

 

幂乘取余

法1:

       (a^b) % c = ( (a%c)^(b%c) ] % c

法2:

       将幂乘求余转换为乘法求余

       (a*b) % c = ( (a%c) * (b%c) )%c

       设 s = b/2;  f = b%2.  则 b = s*2 + f

       a^b  = a^(s*2 + f) = [(a^s)^2] * (a^f)

       f为1或0,只需递归求出a^s即可。  

例:求D=C^15 % N,由于:a*b % n = ((a % n)*(b % n)) % n,所以:C1 =C*C % N =C^2 % NC2 =C1*C % N =C^3 % NC3 =C2*C2 % N =C^6 % NC4 =C3*C % N =C^7 % NC5 =C4*C4 % N =C^14 % NC6 =C5*C % N =C^15 % N

即:对于b=15的幂模运算可分解为6 个乘模运算,归纳分析以上方法可以发现对于任意b,都可采用以下算法计算D=a^b % c:

 

while(b>0)
{
    if(b%2==0)
    { 
        result=(result*result)%c;          // result初始值为1
        b=b/2;
    }
    else
    { 
        result=(result*a)%c;
        b=b-1;                              
    }
}

//继续分析会发现,要知道E何时能整除 2,并不需要反复进行减一或除二的操作,只需验证E 的二进制各位是0 还是1 就可以,所以:

while(b)              //求b的二进制,存放在数组int x[]中
{
    x[i++]=b%2;           
    b=b>>1;         //向右移位,此句也可改为b=b/2,意思一样哦
}

for(j=i-1;j>=0;j--)    
{ 
    result=(result*result)%c;        // result初始值为1
    if(x[j]==1)
    {
        result=(result*a)%c;
    }
}


 
 


 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值