#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
}
}
代码 我就不简化了 记住这个方法就行 其他方法更不用说 有的是 只是在此说明此方法 仅此而已