大数 阶乘1-7万 斐波那契1-40万 n^M次幂 2^2--70000^60000次幂

 

#include <stdio.h>
# include <stdlib.h>
#define  SIZE  77200   //70000!需要77198个int空间
# define size 9290    //第40万个斐波那契需要9290个int的存储空间
# define WEI 10000   //阶乘与乘方每满10000 进位一次 
# define MAX 1000000000//斐波那契每一个int存9位
int JCorCF(int n,int m,int data[]);//计算m的阶乘 或者 n的m次幂 n<1时计算m的阶乘
int FBNQ(int a[][size],int b); //求第b个斐波那契数
int print(int data[],int index,int choose);//输出位数和结果并初始化
int gainint(int *p,int a,int b);//输入int *p直至满足(a,b)输入结束,并返回*p的值
int main()
{
	int FB[3][size]={0},JC[SIZE]={0},SS[2],index,i,choose;
	char JM[][35]={"请输入N [1,70000]:\n","显示第几个斐波那契?[1,400000]:\n","输入N [2,70000]"};
    int domain[][2]={{1,70000},{1,400000},{2,70000}};
	do{
    printf("0:大数阶乘\n1:大数斐波那契\n2:大数N的M次方\n3:退出\n输入选择[0,3]:");
	gainint(&choose,0,3);//用户选择
	if(choose==3) return 0;
	printf("%s",JM[choose]);//输出提示
	gainint(&SS[0],domain[choose][0],domain[choose][1]);//输入
	if(choose==2)//如果是N的M次幂
	{
		printf("输入M [2,60000]:");
		gainint(&SS[1],2,60000);
		print(JC,JCorCF(SS[0],SS[1],JC),choose);//输出N^M次幂
	}
	else if(choose==1)  //输出斐波那契
	{
		index=FBNQ(FB,SS[0]);
		print(FB[(SS[0]-1)%3],index,choose);
		for(i=0;i<=index;i++)//初始化
			FB[(SS[0]-1)%3][i]=FB[SS[0]%3][i]=0;
	}
	else if(!choose)//否则阶乘
		print(JC,JCorCF(0,SS[0],JC),choose);
	system("cls");
	}while(1);
	return 0;
}
int gainint(int *p,int a,int b)//输入int *p直至满足(a,b)输入结束,并返回*p的位数      
{       
    do{      
        *p=a-1;    
        scanf("%d",p);      
        while(getchar()!='\n');      
        if(*p>b||*p<a)      
            printf("输入有误,请重新输入(%d--%d):\n",a,b);      
    }while(*p>b||*p<a);      
    return *p;      
} 
int JCorCF(int n,int m,int data[])
{
	int i,j,k;
	int index =1;        //位数暂定为1
	data[1]=1;           /* 初始化,令2^0=1 */
	for (i=1;i<=m;i++)  /* 计算n的m次幂或m的阶乘*/
	{
		if(n<1)for(j=1;j<=index;j++)
			data[j]=data[j]*i;/*每一位数字都乘以n,模仿乘法计算*/
		else for (j=1;j<=index;j++)
			data[j]=data[j]*n;/*每一位数字都乘以i,模仿乘法计算*/
		for(k=1;k<index;k++)
			if(data[k]>=WEI)   
			{
				data[k+1]+=data[k]/WEI;  /* 当前位向前进位 */
				data[k]%=WEI;            /*当前位进位之后的值 */
			}
			/* 单独处理最高位,若计算之后的最高位>=WEI,则位数index加1 */
			while(data[index]>=WEI&&index<=SIZE-1)
			{
				data[index+1]=data[index]/WEI;  /* 向最高位进位 */
				data[index++]%=WEI;    /* 进位之后的值 位数index加1 */
			}
	}
	return index<=SIZE-1?index:0;/* 检验数组是否溢出,若未溢出,则返回位数 */
}    
int FBNQ(int a[][size],int b)
{
	int i,j,m,k,c[]={0,1,2},index=1;
	a[0][1]=a[1][1]=1;/*初值为1  1*/
	for (i=1;i<=b;i++)
	{
		for (j=1;j<=index; j++)
			a[c[2]][j]=a[c[0]][j]+a[c[1]][j];
		for (k=1;k<index; k++)
			if (a[c[2]][k]>=MAX) 
			{
				a[c[2]][k+1]+=a[c[2]][k]/MAX;  /* 当前位向前进位 */
				a[c[2]][k]%=MAX;             /*当前位进位之后的值 */
			} 
			while (a[c[2]][index]>=MAX&&index <=size-1)
			{
				a[c[2]][index+1] = a[c[2]][index]/MAX;  /* 向最高位进位 */
				a[c[2]][index++]%=MAX;    /* 进位之后的值,位数+1*/
			}
			for(m=0;m<3;m++)
				c[m]=(c[m]+1)%3;//对c[0--2]循环做加法
	} 
	return (index<=size-1)?index:0;
}
int print(int data[],int index,int choose)
{
    int sum=(index-1)*(choose==1?9:4);
    if (index)                //检验数组是否溢出,若未溢出,则打印值 */
	{
		sum+=printf("%d",data[index]);
        data[index--]=0;
	}
	while(index>0)
	{
		if(choose!=1)
			printf("%04d",data[index]);
		else
			printf("%09d",data[index]);
        data[index--]=0;
	}
	printf("\n共%d位\n",sum);
	system("pause");
	return sum;
} 

附加一个数组右移的

假设有个数组A[N]  

要把A 的元素循环右移k 位,则

A[0]移至A[k],A[k]移至A[2k]......直到最终回到A[0].        然而这并没有全部解决问题,因为有可能有的元素在此过程中始终没有被访问过,而是被跳了过去]

.分析可知,当n 和k 的最大公约数为p 时,只要分别以A[0],A[1],...A[p-1]为起点执行上述移动,就可以保证每一个元素都被且仅被右移一次

假设有两个数 a b  (a&&b>=1),设a b的最大公因数为C  则从0----max(a,b)的数轴上 可以最少地平均分成max(a,b)/C个部分 且 a,b都为断点 即a b 处都是被分割的点

 eg  在0---max(a,b)的数轴上 

0     1 23a 5 b  

假设b>a      a为4   b为6   则C为2      也就是说从0开始向数轴正方向行走  

每C=2个格子走一步 可以以最少的步数同时经过a=4  b=6  走过的地方即为断点

  因为格子被最少平均分成了max(4,6)/C  =3个大格子  每一个大格子的数的数量其他的大格子的数的数量  相等且一一对应

只要分别以0,1,为起点执行向右移动C格 就可以保证每一个元素都被且仅被右移一次

# include <stdio.h>
# define N 13   //如果想录入x个字节那么就把N的数值改成x+1
void LYn(int *A,int m,int n);//把数组A[m]的元素右移N位
int main(){
	int A[N]={0},i;
	for(i=0;i<N;i++)
	{
		A[i]=N*i;
		printf("%4d ",A[i]);
	}
    LYn(A,N,4);
	printf("\n左移%d位后:\n",4);
    for(i=0;i<N;i++)
		printf("%4d ",A[i]);
	LYn(A,N,N-4);
	printf("\n右移%d位后:\n",N-4);
    for(i=0;i<N;i++)
		printf("%4d ",A[i]);
    return 0;
}
void LYn(int *A,int m,int k)//把数组A[m]的元素右移N位
{
	int i,j,p,l,temp;
    for(i=1;i<=k;i++)
		if(m%i==0&&k%i==0) p=i;//求n 和k 的最大公约数p
		for(i=0;i<p;i++)
		{
			j=i;
			l=(i+k)%m;
			while(l!=i)
			{
				temp=A[l];   //交换l j
				A[l]=A[j];
				A[j]=temp; 
				j=l;    //刷新j  l 
				l=(j+k)%m;
			}// 循环右移一步
			//for
		}
}

代码 我就不简化了  记住这个方法就行 其他方法更不用说  有的是  只是在此说明此方法  仅此而已 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值