公因数之和2-18446744073709551615

/*输入两个正整数,求这两个数的所有公因数之和
在一般的程序中,都采用循环,两个数字小还可以,但是当两个数非常大,假如都是4294967291时将耗费很长时间,本代码采用辗转相除法和欧拉法判断质数,可以轻松的在0.5S内求出2-4294967295的任意两个数的公因数之和:
代码如下:*/
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
typedef unsigned long  Elem;
Elem zhishu(Elem a);
Elem gys(Elem m,Elem n);
void main(){
	Elem a[]={0,0,0,0},i;
	char aa[][3]={"一","二"};
	long double sum=0;
    do{
		for(i=0;i<2;i++)         //输入两个数存在a[0],a[1]中
			while(a[i]<2||a[i]>4294967295)                 //1排除在外 
			{ 
				printf("输入第%s个数(2--4294967295):",aa[i]); 
				scanf("%lu",&a[i]); 
				while(getchar()!='\n'); 
				if(a[i]<2||a[i]>4294967295)
					printf("输入有误,请重新");
			}
			printf("%lu与%lu的公因数之和\n",a[0],a[1]);
            a[3]=a[2]=gys(a[0],a[1]);    //a[2]=a[3]存有a[0],a[1]的最大公因数
			for(i=1;i<a[3];i++)//a[2]不动,对a[3]进行更改,从1开始;
				if(a[2]%i==0)//当a[2]整除i时
				{
					a[3]=a[2]/i;   //循环主要在数大的时候浪费时间,因为数大的地方公因数密度少,用a[3]存储数大的公因数
					sum+=i;         
					if(i<a[3])
					{
						sum+=a[3];
						printf("%lu %lu ",i,a[3]);
						if(zhishu(a[3]))     //此处主要在数字大的地方节省时间,比如4294967291,没有这句话,要花费很长时间
							break;
					}
					else if(i==a[3])
						printf("%lu ",i);
				} 
				printf("\n=%.0lf",sum+(a[2]-1?0:1));         //当用户输入4200000000时,如果不用double 存储,则超限
				do{
					printf("\n1:重新做\n2:退出\n3:清屏+重做:\n"); 
					scanf("%lu",&i); 
					while(getchar()!='\n');
				}while(i<1||i>3);
				sum=a[0]=a[1]=a[2]=0;   //对a[3]保留因为循环的第一句话只适合程序运行开始时提示一下
				if(i==3)
					system("cls");
	}while(i-2);
}
Elem zhishu(Elem a)                //欧拉判断质数 
{ 
	Elem i,b;
	b=sqrt(a);
	for(i=2;i<=b;i++)                 
		if(a%i==0) return 0;              //为合数时返回0 
		return a;                       //否则返回本身,包含a=1的情形,即把1看成质数
}
Elem gys(Elem m,Elem n)//辗转相除法求mn的最大公因数,m&&n!=0
{ 
    Elem A,B; 
    if(n>m) 
	{ 
		A=m;m=n;n=A;   //保证m>n 
    } 
	while((B=m%n)!=0) 
    { 
		m=n;n=B; 
    } 
    return n; 
} 


在visualc++6.0中unsigned __int64无法以形参的方式传入sqrt()函数中而__int64 可以,所以在用到大数的时候,可以稍微改一些地方而不用重写sqrt()函数,

如果我要输入a=18446744073709551615,那么要计算它的平方根可以将其除以4或其他数,用__int64 b=a/2;b=sqrt(2)*sqrt(b);这样就可以得到大概的值,如要求

16446744073709551615是否为质数,那么可以用以下代码:

当然代码可以优化,不过这样看的更直观一些.

这样就可以求2-18446744073709551615所有的质数;

typedef unsigned __int64 Elem;

Elem zhishu(Elem a)                //欧拉法判断质数 

Elem i;
long double c=0;
__int64 b=0;
if(a>=N)
{
  b=a/2;
  b=sqrt(2)*sqrt(b);
}
    else
{
b=a;
b=sqrt(b);
}
for(i=2;i<=b;i++)                 
if(a%i==0) return 0;              //为合数时返回0 
return a;                       //否则返回本身,包含a=1的情形,即把1看成质数
}

由此可以求2-18446744073709551615中的--任意两个数的所有公因数之和:

代码如下:

# include <stdio.h>
# include <stdlib.h>
# include <math.h>
typedef  unsigned __int64  Elem;
const  __int64 N=9223372036854775807;//__int64的最大值
const  unsigned __int64 UN=18446744073709551615;
const unsigned __int64 INDEX=1000000000000000000;//每十八位进一位
Elem sum[3]={0,0,0};
Elem zhishu(Elem a);
Elem gys(Elem m,Elem n);
void main(){
Elem a[]={0,0,0,0},i;
int j=0,k=0;
char aa[][3]={"一","二"};
    do{
for(i=0;i<2;i++)         //输入两个数存在a[0],a[1]中
while(a[i]<2)                 //1排除在外 
{ 
printf("输入第%s个数(2--%I64u):\n",aa[i],UN); 
scanf("%I64u",&a[i]); 
while(getchar()!='\n'); 
if(a[i]<2)
printf("输入有误,请重新");
}
printf("%I64u与%I64u的公因数之和\n",a[0],a[1]);
            a[3]=a[2]=gys(a[0],a[1]);    //a[2]=a[3]存有a[0],a[1]的最大公因数
for(i=1;i<a[3];i++)//a[2]不动,对a[3]进行更改,从1开始;
if(a[2]%i==0)//当a[2]整除i时
{
a[3]=a[2]/i;   //循环主要在数大的时候浪费时间,因为数大的地方公因数少,用a[3]存储数大的公因数
sum[0]+=i; 
while(sum[j]>=INDEX)
{
sum[j+1]+=sum[j]/INDEX;
sum[j++]%=INDEX;
k=j;
}
j=0;
if(i<a[3])
{
sum[0]+=a[3];
while(sum[j]>=INDEX)
{
sum[j+1]+=sum[j]/INDEX;
sum[j++]%=INDEX;
k=j;
}
j=0;
printf("%I64u %I64u ",i,a[3]);
if(zhishu(a[3])) 
break;
}
else if(i==a[3])
printf("%I64d ",i);
}
sum[j]+=(a[2]-1?0:1);
printf("\n=%I64u",sum[k--]);
if(k>=0)
printf("%018I64u",sum[k]);
do{
printf("\n1:重新做\n2:退出\n3:清屏+重做:\n"); 
scanf("%I64u",&i); 
while(getchar()!='\n');
}while(i<1||i>3);
sum[0]=sum[1]=sum[2]=0;
a[0]=a[1]=a[2]=j=k=0;
if(i==3)
system("cls");
}while(i-2);
}
Elem zhishu(Elem a)                //欧拉判断质数 
{ 
Elem i;
long double c=0;
__int64 b=0;
if(a>=N)
{
  b=a/2;
  b=sqrt(2)*sqrt(b);
}
    else
{
b=a;
b=sqrt(b);
}
for(i=2;i<=b;i++)                 
if(a%i==0) return 0;              //为合数时返回0 
return a;                       //否则返回本身,包含a=1的情形,即把1看成质数
}
Elem gys(Elem m,Elem n)//辗转相除法求mn的最大公因数,m&&n!=0
{ 
    Elem A,B; 
    if(n>m) 
{ 
A=m;m=n;n=A;   //保证m>n 
    } 
while((B=m%n)!=0) 
    { 
m=n;n=B; 
    } 
    return n; 
} 
/*虽然当数非常大时这个求解时间也很长,但是也算是很有效率了*/


质因数分解器v1.1采用C语言编写,可以分解0~2^64-1的数,速度很快。 部分数字的分解结果: ************************************************** * Factorization v1.1 * DevilHand Presents 2011-03-18 * Email: DevilHand@126.com ************************************************** Input a number: 12157665459056928801 Result: 12157665459056928801 = 3^40 ************************************************** Input a number: 9966332255887744111 Result: 9966332255887744111 is a prime number. ************************************************** Input a number: 18446744073709551520 Result: 18446744073709551520 = 2^5 x 5 x 2663 x 43294085790719 ************************************************** Input a number: 18446744073709551608 Result: 18446744073709551608 = 2^3 x 2305843009213693951 ************************************************** Input a number: 10459 Result: 10459 is a prime number. ************************************************** Input a number: 90541 Result: 90541 = 11 x 8231 ************************************************** Input a number: 142857 Result: 142857 = 3^3 x 11 x 13 x 37 ************************************************** Input a number: 428571 Result: 428571 = 3^4 x 11 x 13 x 37 ************************************************** Input a number: 999999 Result: 999999 = 3^3 x 7 x 11 x 13 x 37 ************************************************** Input a number: 951463287 Result: 951463287 = 3^3 x 23 x 547 x 2801 ************************************************** Input a number: 614889782588491410 Result: 614889782588491410 = 2 x 3 x 5 x 7 x 11 x 13 x 17 x 19 x 23 x 29 x 31 x 37 x 41 x 43 x 47 ************************************************** Input a number: 142857142857 Result: 142857142857 = 3^3 x 11 x 13 x 37 x 101 x 9901 ************************************************** Input a number: 114422885577 Result: 114422885577 = 3^4 x 7 x 11 x 13 x 37 x 43 x 887 ************************************************** Input a number: 9080706050403020100 Result: 9080706050403020100 = 2^2 x 3^2 x 5^2 x 229 x 547 x 8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值