新浪博客 发表时间 --2009-07-26 20:11:01
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> A^B mod C</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
题解:
解法一:可套公式,A*B mod C=((A mod C)*(B mod C) mod C ;A^B mod C=(A mod C)^(B mod C) mod C。
数据如果过大,则要考虑其他方法,此题的解法用到了逐次平方法(幂模运算)。具体实现过程参考数论相关的书籍。
<wbr></wbr>
需要注意的是,要小心溢出问题,比如a=a*b%c,如果简单这样计算的时候,如果a足够大的时候,就会导致溢出,处理方法为取a二进制值第一位乘以b与c模算加上a右移一位与相乘再和c做模运算后的值左移一位相加,再将相加的值和c做模运算,递归此过程,过程结束标志为a=0。
代码:
#include<stdio.h>
unsigned long long mul(unsigned long long a,unsigned long long b,unsigned long long c)
{
unsigned long long int a1=a,b1=b,c1=c;
if(!a1)
<wbr><wbr> return 0;<br><wbr><wbr><wbr> return (((a1&1)*b1)%c1+(mul(a1>>1,b1,c1)<<1)%c1)%c1;<br>
}</wbr></wbr></wbr></wbr></wbr>
unsigned long long mod(unsigned long long a,unsigned long long b,unsigned long long c)
{
<wbr><wbr> unsigned long long y=1;<br><wbr><wbr> while(b)<br><wbr><wbr> {<br><wbr><wbr><wbr><wbr><wbr> if(b%2==1)<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr> y=mul(y,a,c);<br><wbr><wbr><wbr><wbr><wbr> a=mul(a,a,c);<br><wbr><wbr><wbr><wbr><wbr> b=b>>1;<br><wbr><wbr> }<br><wbr><wbr> return y;<br>
}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
int main()
{
<wbr><wbr> unsigned long long a,b,c;<br><wbr><wbr> while(scanf("%llu%llu%llu",&a,&b,&c)!=EOF)<br><wbr><wbr><wbr><wbr><wbr><wbr> printf("%llu\n",mod(a,b,c)%c);<br><wbr><wbr> return 0;<br>
}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
解法二:
<wbr><wbr> 当数很大时比如快接近2的63次方时,解法一就不行,会溢出。要不溢出就得改变下解法一的mul函数,具体改变如下:</wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></wbr></wbr>
unsigned long long mul(unsigned long long a,unsigned long long b,unsigned long long c)
{
unsigned long long ret=0,tmp=a%c;
while(b)
{
<wbr><wbr> if(b&0x1)<br><wbr><wbr><wbr> if((ret+=tmp)>=c)<br><wbr><wbr><wbr><wbr> ret-=c;<br><wbr><wbr><wbr> if((tmp<<=1)>=c)<br><wbr><wbr><wbr><wbr> tmp-=c;<br><wbr><wbr><wbr> b>>=1;<br>
}<br>
return ret;<br>
}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
这个函数是网上找的,现在是看不懂,研究中....
解法三:
代码:
#include "stdio.h"
int power(int a,int b,int c)
{
<wbr>int tmp;<br><wbr>if (b==0)<br><wbr>{<br><wbr><wbr>return 1;<br><wbr>}<br><wbr>tmp=power((a*a)%c,b/2,c);<br><wbr>if (b%2!=0)<br><wbr>{<br><wbr><wbr>tmp=(tmp*a)%c;<br><wbr>}<br><wbr>return tmp;<br>
}<br>
int main()<br>
{<br><wbr>int a,b,c;<br><wbr>while(scanf("%d %d %d",&a,&b,&c)!=EOF)<br><wbr>{<br><wbr><wbr>printf("%d\n",power(a,b,c));<br><wbr>}<br>
}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
分享到:
相关推荐
代Un的还没被Ac,其余不保证算法够好,只是随便传传
给定一个自然数n,由n开始可以依次产生半数集set(n)中的数如下。 (1)n∈set(n); (2)在n的左边加上一个自然数,但该自然数不能超过最近添加的数的一半; (3)按此规则进行处理,直到不能再添加自然数为止。...
FOJ(大部分标程) ACMFOJ(大部分标程) ACMFOJ(大部分标程) ACMFOJ(大部分标程) ACMFOJ(大部分标程) ACMFOJ(大部分标程) ACM
第一次上传东西... 本人是个初学者,希望大家多多指教
Source code example for shortcuts to create arbitrary files on the command line