C语言程序设计100例之(66):计算2的N次方
例66 计算2的N次方
问题描述
任意给定一个正整数N(1<=N<=100),计算2的n次方的值。
输入
输入一个正整数N。
输出
输出2的N次方的值。
输入样例
5
输出样例
32
(1)编程思路1。
当N=100时,2的N次方是一个很大的数,超出了一个长整数的表数范围。因此,为了保存2的N次方,可以定义一个数组int a[35];,每个数组元素a[i]保存结果整数的1位数,例如,保存整数1024时,a[0]=4,a[1]=2,a[2]=0,a[3]=1,并记整数的位数len=4。
这样一个整数乘以2,可以将每个数组元素乘以2,同时进行进位处理即可。
(2)源程序1。
#include <stdio.h>
#include <string.h>
int main()
{
int n;
scanf("%d",&n);
int a[35];
memset(a,0,sizeof(a));
a[1]=1;
int i,j,len=1;
for(i=1;i<=n;i++)
{
int cf=0;
for (j=1;j<=len;j++)
{
a[j]=a[j]*2+cf;
cf=a[j]/10;
a[j]=a[j]%10;
}
while (cf!=0)
{
a[++len]=cf%10;
cf/=10;
}
}
for (i=len;i>=1;i--)
printf("%d",a[i]);
printf("\n");
return 0;
}
(3)编程思路2。
一个数组元素只保存整数的1位数字,这样既浪费存储空间,同时耗时。实际上,一个数组元素可以保存9位数字都没有问题,因为1个9位数乘以2,不会超过整数的表数范围。
下面的程序采用1个数组元素保存整数的6位数字。例如,整数1234567890,可以保存为a[0]=567890,a[1]=1234,并记整数的位数len=2。
(4)源程序2。
#include <stdio.h>
#include <string.h>
#define BASE 1000000
int main()
{
int n;
scanf("%d",&n);
int a[7];
memset(a,0,sizeof(a));
a[1]=1;
int i,j,len=1;
for(i=1;i<=n;i++)
{
int cf=0;
for (j=1;j<=len;j++)
{
a[j]=a[j]*2+cf;
cf=a[j]/BASE;
a[j]=a[j]%BASE;
}
while (cf!=0)
{
a[++len]=cf%BASE;
cf/=BASE;
}
}
printf("%d",a[len]);
for (i=len-1;i>=1;i--)
printf("%06d",a[i]);
printf("\n");
return 0;
}
习题66
66-1 求10000以内n的阶乘
问题描述
求10000以内n的阶乘。
输入
只有一行输入,整数n(0<=n<=10000)。
输出
一行,即n!的值。
样例输入
100
样例输出
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
(1)编程思路。
10000以内n的阶乘是一个很大的数,超出了一个长整数的表数范围。因此,为了保存n的阶乘,可以定义一个数组int a[2000];,每个数组元素a[i]保存结果整数的4位数字,例如,保存整数1234567890时,a[0]=7890,a[1]=3456,a[2]=12,并记整数的位数len=3。
这样一个整数乘以K(1,=k<=N),可以将每个数组元素乘以K,同时进行进位处理即可。
(2)源程序。
#include <stdio.h>
#include <string.h>
#define BASE 10000
int main()
{
int n;
scanf("%d",&n);
int a[2000];
memset(a,0,sizeof(a));
a[1]=1;
int i,j,len=1;
for(i=2;i<=n;i++)
{
int cf=0;
for (j=1;j<=len;j++)
{
a[j]=a[j]*i+cf;
cf=a[j]/BASE;
a[j]=a[j]%BASE;
}
while (cf!=0)
{
a[++len]=cf%BASE;
cf/=BASE;
}
}
printf("%d",a[len]);
for (i=len-1;i>=1;i--)
printf("%04d",a[i]);
printf("\n");
return 0;
}
66-2 吃巧克力
问题描述
小红的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给小红(盒内共有 N 块巧克力,1000 > N >0)。妈妈告诉小红每天可以吃一块或者两块巧克力。假设小红每天都吃巧克力,问小红共有多少种不同的吃完巧克力的方案。例如:如果N=1,则小红第1天就吃掉它,共有1种方案;如果N=2,则小红可以第1天吃1块,第2天吃1块,也可以第1天吃2块,共有2种方案;如果N=3,则小红第1天可以吃1块,第2天吃1块,第3天吃1块,也可以第1天吃1块,第2天吃2块,还可以第1天吃2块,第2天吃1块,所以小红共有3种方案。现在给定N,请你写程序求出小红吃巧克力的方案数目。
输入
输入只有1行,即整数N。
输出
输出只有1行,即小红吃巧克力的方案数。
输入样例
3
输出样例
3
(1)编程思路。
设f[n]表示小红吃n个巧克力的方案数目。
由于小红每天可以吃一块或者两块巧克力,若最后一天小红吃1个巧克力,则有f[n-1]种方案;若最后一天小红吃2个巧克力,则有f[n-2]种方案;因此,f[n]= f[n-1]+ f[n-2]。
由于n较大,f[n]超过了一个长整数的表数范围,所以用数组保存一个整数的各位。
定义二维数组int f[1005][301],其中第1维f[i]表示吃i个巧克力的方案数。第2维用于保存各整数的各位数字,每个元素保存一个数字,其中f[i][0]保存吃i个巧克力的方案数x的位数,f[i][1]~f[i][f[i][0]]分别保存x从低位到高位的各位数字。
(2)源程序。
#include <stdio.h>
#include <string.h>
int main()
{
int n;
scanf("%d",&n);
int f[1005][301];
memset(f,0,sizeof(f));
f[1][0]=1;
f[1][1]=1;
f[2][0]=1;
f[2][1]=2;
int i,j;
for (i=3;i<=n;i++)
{
int len=f[i-1][0];
int cf=0;
for (j=1;j<=len;j++)
{
f[i][j]=f[i-1][j]+f[i-2][j]+cf;
cf=f[i][j]/10;
f[i][j]=f[i][j]%10;
}
if (cf!=0)
f[i][++len]=cf;
f[i][0]=len;
}
for (i=f[n][0];i>=1;i--)
printf("%d",f[n][i]);
printf("\n");
return 0;
}
66-3 钥匙的放置
问题描述
设有n(3<=n<=200)个盒子,由A1、A2、…、An分别标识。每个盒子都配置了一个不同于其他盒子的锁。现在把n把钥匙锁进这n个盒子里,每个盒子只能装一把钥匙。锁好所有盒子后,撬开A1、A2两个盒子,取出里面的钥匙,打开相应锁好的盒子。如果这两把钥匙可以打开某个盒子,取出盒子里的钥匙,再次解锁其他锁定的盒子。
问能够最终打开所有盒子的钥匙的放置方法有多少种。
输入
输入文件以-1结尾,包含多个数据,每个数据占一行。
输出
根据每个输入数据,计算最终打开所有盒子的钥匙的放置方法数。每个输出数据保留两行,第一行由输入数据保留,后面是冒号,冒号后面是等号,前面是N;第二个是放置的方法数。
输入样例
6
8
-1
输出样例
N=6:
240
N=8:
10080
(1)编程思路。
钥匙的放置可以采用如下两种方案:
1)所有钥匙形成一个环,以一个钥匙(1或2)为起点可以到达所有钥匙,这样可以1或2中一个点为起始点依次打开所有盒子,所有钥匙环排列,方案数有(n-1)!种。
2)以1和2为起点分别形成两个环,两个环的大小就是方程x+y=n的正整数解,这个方程有n-1个解,剩下的n-2个钥匙可以全排列,作为各环上的顺序,有(n-1)*(n-2)!种方案。
所以总方案数为2*(n-1)!。
定义一个数组int a[410];来保存总方案数,每个数组元素a[i]保存结果整数的1位数。
(2)源程序1。
#include <stdio.h>
#include <string.h>
int a[410];
void fact(int n) // 求阶乘
{
memset(a,0,sizeof(a));
a[1]=2;
int i,j,len=1;
for(i=2;i<=n;i++)
{
int cf=0;
for (j=1;j<=len;j++)
{
a[j]=a[j]*i+cf;
cf=a[j]/10;
a[j]=a[j]%10;
}
while (cf!=0)
{
a[++len]=cf%10;
cf/=10;
}
}
for (i=len;i>=1;i--)
printf("%d",a[i]);
printf("\n");
}
int main()
{
int n;
while(scanf("%d",&n) &&n!=-1)
{
printf("N=%d:\n",n);
fact(n-1);
}
return 0;
}
上面的程序采用一维数组保存2*(n-)!。可以定义一个二维数组int a[201][410];,将n=3~200的方案数全部保存下来,因为n!=n*(n-1)!,这样无需每次求方案数时,都进行阶乘的运算。按这样的思路,编写如下的源程序。
(3)源程序2。
#include <stdio.h>
#include <string.h>
int a[201][410];
void init(void) // 求阶乘
{
memset(a,0,sizeof(a));
a[1][0]=1;
a[1][1]=2;
int i,j,len=1;
for(i=2;i<=200;i++)
{
int cf=0;
for (j=1;j<=len;j++)
{
a[i][j]=a[i-1][j]*i+cf;
cf=a[i][j]/10;
a[i][j]=a[i][j]%10;
}
while (cf!=0)//
{
a[i][++len]=cf%10;
cf/=10;
}
a[i][0]=len;
}
}
int main()
{
int n,i;
init();
while(scanf("%d",&n) &&n!=-1)
{
printf("N=%d:\n",n);
for (i=a[n-1][0];i>=1;i--)
printf("%d",a[n-1][i]);
printf("\n");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)