ACM必做50题的解题数论文档格式.docx

上传人:b****6 文档编号:20250616 上传时间:2023-01-21 格式:DOCX 页数:24 大小:22.29KB
下载 相关 举报
ACM必做50题的解题数论文档格式.docx_第1页
第1页 / 共24页
ACM必做50题的解题数论文档格式.docx_第2页
第2页 / 共24页
ACM必做50题的解题数论文档格式.docx_第3页
第3页 / 共24页
ACM必做50题的解题数论文档格式.docx_第4页
第4页 / 共24页
ACM必做50题的解题数论文档格式.docx_第5页
第5页 / 共24页
点击查看更多>>
下载资源
资源描述

ACM必做50题的解题数论文档格式.docx

《ACM必做50题的解题数论文档格式.docx》由会员分享,可在线阅读,更多相关《ACM必做50题的解题数论文档格式.docx(24页珍藏版)》请在冰豆网上搜索。

ACM必做50题的解题数论文档格式.docx

+b*(x'

-a/b*y'

=a*x+b*y

则:

x=y'

y=x'

以上内容转自

 

由这个可以得出扩展的欧几里德算法:

intexGcd(inta,intb,int&

x,int&

y)

if(b==0)

x=1;

y=0;

intr=exGcd(b,a%b,x,y);

intt=x;

x=y;

y=t-a/b*y;

returnr;

代码:

#include<

iostream>

cstdlib>

cstring>

cmath>

usingnamespacestd;

__int64mm,nn,xx,yy,l;

__int64c,d,x,y;

__int64modd(__int64a,__int64b)

if(a>

=0)

returna%b;

else

returna%b+b;

__int64exGcd(__int64a,__int64b)

if(b==0)

{

x=1;

y=0;

}

__int64r=exGcd(b,a%b);

__int64t=x;

x=y;

y=t-a/b*y;

intmain()

scanf("

%I64d%I64d%I64d%I64d%I64d"

&

xx,&

yy,&

mm,&

nn,&

l);

if(mm>

nn)//分情况

d=exGcd(mm-nn,l);

c=yy-xx;

}

d=exGcd(nn-mm,l);

c=xx-yy;

if(c%d!

printf("

Impossible\n"

);

return0;

l=l/d;

x=modd(x*c/d,l);

///取模函数要注意

%I64d\n"

x);

system("

pause"

}

POJ1142SmithNumber

题意:

寻找最接近而且大于给定的数字的SmithNumber

什么是SmithNumber?

用sum(int)表示一个int的各位的和,那一个数i如果是SmithNumber,则sum(i)=sigma(sum(Pj)),Pj表示i的第j个质因数。

例如4937775=3*5*5*65837,4+9+3+7+7+7+5=42,3+5+5+(6+5+8+3+7)=42,所以4937775是SmithNumber。

思路:

要寻找大于给定数字且最接近给定数字的SmithNumber,只要将给定数字不断的加1,判断它是否是SmithNumber就行了,如果是SmithNumber就立即输出。

但是如何判断是否是SmithNumber呢?

首先就是要对数字进行质因数分解。

质因数分解要保证因子都是质数。

这里先介绍一个如何判断一个数int是否是质数呢,如果对于这个数,i=2.....sqrt(int)都不是它的约数,那int就是一个质数。

所以我们可以将i初始化为2,然后不断递增i,看i是否是int的一个约数,如果是的话那i就是int的一个质因数(因为这个数是从2开始第一个可以整除int的数,它不可能是一个可以分解的合数,否则,它的约数在它之前就整除int),然后将int除以该质因数,重置i为2,重新对int判断它是否是质数。

这样最后剩下的int一定是一个质数,从而对int进行了质因数分解

然后就很简单的将数字各质因数的各位加起来,看和是否等于该数字的各位和,如果相等那它可能就是SmithNumber,为什么说只是可能呢,因为这个数可能是质数,但是质数不是SmithNumber。

#include<

stdio.h>

math.h>

intSum(intnumber)

intsum=0;

while(number!

=0)

sum+=number%10;

number/=10;

returnsum;

boolSmithNumber(intnumber)

inti=2;

inttemp=number;

intsumOfNumber=Sum(number);

while(i<

=(int)sqrt((double)number))

if(number%i==0)

sum+=Sum(i);

number/=i;

i=2;

++i;

//以上的代码做了无谓的计算,可用下面的代码,更新于20090904

//while(number%i==0)

//{

//sum+=sum(i);

//number/=i;

//}

//++i;

sum+=Sum(number);

if(sum==sumOfNumber&

&

number!

=temp)

returntrue;

else

returnfalse;

while(true)

intnum;

%d"

num);

if(num==0)

break;

while(true)

if(SmithNumber(++num))

%d\n"

num);

return0;

ACM——POJ2262(Goldbach'

sConjecture)

题目地址:

题目思路:

对于任何一个偶数n,从x=1和y=n-1开始,看x、y是否是质数,不是则x+=2,y+=2

这题需要开很大的内存,我REn次,居然是因为数组开太小了,我这题耗时不是很理想,但我的耗内存

在我看到的中是最小的,所以看来OJ上的题只要能开内存的就尽量开。

估计我这题用栈耗时了。

stack>

memory.h>

string.h>

//判断是否为质数的函数

intIsPrime(intx)

{

inti;

if(x<

2)

for(i=2;

i<

=(int)(sqrt((double)x+0.5));

i++)

if(x%i==0)

return1;

intmain()

//输入数,输入数/2向上延伸,输入数/2向下延伸,输入数/2

intm_Input,m_Num_Max,m_Num_Min,m_InputToTwo;

//总体输出

charm_Output[1000000];

memset(m_Output,0,1000000);

//标识m_Output的Pos

intm_Output_Pos=0;

//是否找到标识

boolb_Find;

//栈

stack<

int>

m_Stack;

//临时数

intm_Value_Top;

//循环输入

while(scanf("

&

m_Input)&

(m_Input!

=0))

{

b_Find=true;

//m_Input肯定是一个偶数

m_InputToTwo=m_Input/2;

//置值

m_Num_Max=m_Input-1;

m_Num_Min=1;

//寻找,直至都为素数或者找不到为止

while((!

IsPrime(m_Num_Max))||(!

IsPrime(m_Num_Min)))

//否则,前进&

后退2格

m_Num_Max-=2;

m_Num_Min+=2;

//如果发生如下情况,则输出"

Goldbach'

sconjectureiswrong."

if((m_Num_Max<

m_InputToTwo)||(m_Num_Min>

m_InputToTwo))

char*m_TempChar="

sconjectureiswrong.\n"

;

strcat(m_Output,m_TempChar);

b_Find=false;

m_Output_Pos+=strlen(m_TempChar);

//如果找到了

if(b_Find)

//将m_Input转换为字符串存入m_Output

while(m_Input!

=0)

m_Value_Top=m_Input%10;

m_Stack.push(m_Value_Top);

m_Input/=10;

while(!

m_Stack.empty())

m_Value_Top=m_Stack.top();

m_Output[m_Output_Pos++]=m_Value_Top+48;

m_Stack.pop();

//加入=

m_Output[m_Output_Pos++]='

'

='

//将m_Num_Min转换为字符串存入m_Output

while(m_Num_Min!

m_Value_Top=m_Num_Min%10;

m_Num_Min/=10;

//加入+

+'

//将m_Num_Max转换为字符串存入m_Output

while(m_Num_Max!

m_Value_Top=m_Num_Max%10;

m_Num_Max/=10;

//加入\n

\n'

//输出

printf("

%s"

m_Output);

system("

);

POJ2407Relatives

这题从题意可以看出就是求比从1~n-1从有几个数和n没有公共因子,通常的算法很简单就能够想到,我开始也是按通常的做法写了一个,觉得

可能会TLE,果不其然,后来上网查了一下,知道了欧拉函数,这个就是求比n小的数中与n互质(也就是没有公共因子)的算法,看来还是那些经典的算法效率比较高,比纯用暴力试探高多了...

欧拉函数描述如下:

  利用欧拉函数和它本身不同质因数的关系,用筛法计算出某个范围内所有数的欧拉函数值。

  欧拉函数和它本身不同质因数的关系:

欧拉函数ψ(N)=N{∏p|N}(1-1/p)。

(P是数N的质因数)

  如:

  ψ(10)=10×

(1-1/2)×

(1-1/5)=4;

  ψ(30)=30×

(1-1/3)×

(1-1/5)=8;

  ψ(49)=49×

(1-1/7)=42。

注意的是P是N的质因子,这里求质因子还是不能够用常规的判断这个数是不是质数,这样的话可能还会TLE,网上学到他们用的一个while()循环,感觉还挺巧的,学习了...

intenlerFun(intn)

intcount=n;

inti=2;

for(;

i<

=n;

i++)

if(n%i==0)

count-=count/i;

while(n%i==0)

n/=i;

returncount;

intinputVal=0;

intcount=0;

while(scanf("

inputVal)&

inputVal!

=0)

count=enlerFun(inputVal);

count);

POJ1811PrimeTest

MillerRobin素性测试+Pollardrho寻找素因子

MillerRobin和Pollardrho的理论想非常强,细节这里就不说了,可以参考

算法导论第31章

ctime>

#defineMAX_L64//最长位数

#defineTIMES8//millerrobin素性测试的测试次数

#defineMAX_VAL(pow(2.0,60))//定义最大值

#defineCVAL200

//最小的素因子

__int64minFactor;

//

(1)计算a*bmodn,思路:

利用b的二进制表示进行拆分计算

//

(2)例如:

b=1011101那么a*bmodn=(a*1000000modn+a*10000modn+a*1000modn+a*100modn+a*1modn)modn

//(3)思路就是上面描述的那样,那么可以用从低位往高位遍历b,并用a来记录当前位为1的值,每次遇到b当前位为

//1就将结果值加上a并modn,然后a要乘以2

__int64multAndMod(__int64a,__int64b,__int64n)

a=a%n;

__int64res=0;

while(b)

//当前位为1

if(b&

1)

//加上当前权位值

res+=a;

//相当于modn

if(res>

=n)res-=n;

//乘以2,提高一位

a=a<

<

1;

//modn

=n)a-=n;

b=b>

>

1;

returnres;

//

(1)计算a^bmodn,思路:

和上面类似,也是利用b的二进制表示进行拆分计算

b=1011101那么a^bmodn=[(a^1000000modn)*(a^10000modn)*(a^1000modn)*(a^100modn)*(a^1modn)]modn

//1就将结果乘上a并modn,然后a要乘以a以提升一位

__int64modAndExp(__int64a,__int64b,__int64n)

__int64res=1;

while(b>

=1)

//遇到当前位为1,则让res*当前a并modn

res=multAndMod(res,a,n);

//a*a以提升一位

a=multAndMod(a,a,n);

//MillerRobin素性测试,true:

素数,flase:

合数

boolmillerRobin(__int64a,__int64n)

__int64u=0,cur=n-1;

intt=0;

boolfind1=false;

while(cur!

if(!

find1)

intpb=cur%2;

if(pb==0)t++;

elsefind1=true;

if(find1)

cur=cur/2;

u=cur;

cur=modAndExp(a,u,n);

__int64now;

for(intp=1;

p<

=t;

p++)

now=modAndExp(cur,2,n);

if(cur!

=1&

now==1&

cur!

=n-1)

//printf("

%d%d\n"

cur,now);

cur=now;

a:

%I64du:

%I64dn:

%I64dval:

a,u,n,start);

//利用MillerRobin对n进行n次素性测试

booltestPrime(inttimes,__int64n)

if(n==2)returntrue;

if(n%2==0)returnfalse;

__int64a;

intt;

srand(time(NULL));

for(t=1;

t<

=times;

t++)

a=rand()%(n-1)+1;

millerRobin(a,n))returnfalse;

__int64gcd(__int64a,__int64b)

if(b==0)return(a);

returngcd(b,a%b);

__int64PollardRho(__int64n,intc)

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1