1、大数的阶乘。比如大于10小于1000;
解题过程。我在PTA上做这个题的时候,由于题上的示例输入为15!=1307674368000。所以就一直用15来练习。刚开始的时候由于int类型为21亿多,所以输出的时候超出范围,被截断,答案就不正确。然后,用来long long 类型来表示,其范围在(-2^63~~2^63-1),就能够表示15!。(注意:long long在打印时应该是printf("%lld", N);要在%d前加”ll“)。然后在PTA上测试,结果显示为部分正确,如果取最大值,即计算999!时,long long 类型仍然不能输出(double也超出了范围)。最后通过网上查阅,许多博主的建议是通过数组来存,最后看了一篇通过int类型数组的解决方案的博客,最后成功解决。
思路1:通过long long(或double)类型,能够部分解决,对于太大的数,比如结果超过(-2^63~~2^63-1)的,仍然不行。代码如下
#include <stdio.h>
//打印非负整数的阶乘
void Print_Factorial ( const int N ){
if(N > 0){
long long result = 1; //当超出long long时,仍然不行
for(int i=0; i<N; i++){
result *= i+1;
}
printf("%lld\n", result);
}
else if(N==0)
printf("1");
else if (N<0){
printf("Invalid input");
}
}
int main(){
int N;
scanf("%d", &N);
Print_Factorial(N);
return 0;
}
思路2:借鉴了网上的写法,通过一个数组来存阶乘结果。代码如下
#include <stdio.h>
//打印非负整数的阶乘
void Print_Factorial ( const int N ){
if(N > 0){
int a[3000];
int temp,num,digit; //temp:每一位的结果 num:进位 digit:结果的位数
int i,j;
a[0]=1;
digit=1; //从第1位开始
if(N>0){
for(i=2;i<=N;i++){
num=0;
for(j=0;j<digit;j++){
temp=a[j]*i+num; //+num:表示a[j]有进位,a[j+1]就应该加上num
a[j]=temp%10; //把当前位的数字存入数组
num=temp/10; //向前面一位进位
}
while(num){ //当i的阶乘算完,仍有进位,则数组需扩大
a[digit]=num%10;
num/=10;
digit++;
}
}
for(i=digit-1;i>=0;i--){
printf("%d",a[i]);
}
}
else if(N==0)
printf("1");
else if (N<0){
printf("Invalid input");
}
}
int main(){
int N;
scanf("%d", &N);
Print_Factorial(N);
return 0;
}
大数阶乘结果:比如999!为
2、实现判断给定整数奇偶性的函数。
思路:如果n % 2 =0 那么n为偶数,否则为奇数
#include <stdio.h>
int even( int n ){
if(n % 2 ==0){
return 1;
}else{
return 0;
}
}
int main(){
int N;
scanf("%d", &N);
if(even(N)){
printf("%d is even.\n", N);
}else{
printf("%d is odd.\n", N);
}
return 0;
}
3、实现一个函数,求N
个集合元素A[]
的中位数,即序列中第⌊(N+1)/2⌋大的元素。其中集合元素的类型为自定义的ElementType
。
思路:找中位数,首先将数组A排序,然后找到中间位置,然后返回。我这里采用"快速排序"。
#include <stdio.h>
#define MAXN 10
typedef float ElementType;
//快速排序
void QuickSort(ElementType A[], int start, int end){
int i = start;
int j = end;
ElementType temp = A[start];
if(i<j){
while(i<j){
//右半部分
while(i<j && A[j]>=temp){
j--;
}
if(i<j){
A[i] = A[j];
i++;
}
//左半部分
while(i<j && A[i]<=temp){
i++;
}
if(i<j){
A[j] = A[i];
j--;
}
}
A[i] = temp; //枢轴元素填入i=j的位置
//再递归排序左、右部分
QuickSort(A, start, i-1);
QuickSort(A, j+1, end);
}
}
/*
求数组A中元素的中位数,N表示A中元素个数
思路:将数组A排序
A长度为基数,则中位数为A[N / 2]
A长度为偶数,则中位数为(A[N / 2 - 1] + A[N / 2]) /2
*/
ElementType Median(ElementType A[], int N){
ElementType result;
//将数组A排序,采用快速排序
QuickSort(A, 0, N-1);
if(N % 2 == 0){
result = (A[N / 2 - 1] + A[N / 2]) / 2;
}else{
result = A[N / 2];
}
return result;
}
int main(){
ElementType A[MAXN] = {0};
int N;
scanf("%d", &N);
for(int i=0; i<N; i++){
scanf("%f", &A[i]);
}
printf("%.2f\n", Median(A, N));
return 0;
}
4、
将N个整数按从小到大排序的冒泡排序法是这样工作的:从头到尾比较相邻两个元素,如果前面的元素大于其紧随的后面元素,则交换它们。通过一遍扫描,则最后一个元素必定是最大的元素。然后用同样的方法对前N−1个元素进行第二遍扫描。依此类推,最后只需处理两个元素,就完成了对N个数的排序。
本题要求对任意给定的K(<N),输出扫描完第K遍后的中间结果数列。
注意:对于冒泡的核心部分,当采用从左往右遍历时。内层循环变量j应该从1开始,并且要if(A[j-1]>A[j])作为判断条件
for(int i=0; i<K; i++){//冒泡排序核心算法
for(int j=1; j<N-i; j++){
if(A[j-1]>A[j]){
int temp = A[j-1];
A[j-1] = A[j];
A[j] = temp;
}
}
}
有问题的写法:
for(int i=0; i<K; i++){//冒泡排序核心算法
for(int j=0; j<N-i; j++){
if(A[j]>A[j+1]){
int temp = A[j+1];
A[j+1] = A[j];
A[j] = temp;
}
}
}
如果j从0开始,并且A[j]>A[j+1]作为判断条件的话,当j=N-1时,j+1时数组就已经越界了。在PTA就不能排序成功,而在dev c++上还是能正确,所以要注意。
正确的完整代码:
#include <stdio.h>
int main(){
int N, K;
scanf("%d%d", &N, &K);
int A[N];
for(int m=0; m<N; m++){
scanf("%d", &A[m]);
}
for(int i=0; i<K; i++){//冒泡排序核心算法
for(int j=1; j<N-i; j++){
if(A[j-1]>A[j]){
int temp = A[j-1];
A[j-1] = A[j];
A[j] = temp;
}
}
}
for(int n=0; n<N-1; n++){
printf("%d ", A[n]);
}
printf("%d", A[N-1]);
return 0;
}
注意事项:平时在dev c++运行代码时,对printf("%d ", A[n])输出,在输出最后一个数后还会有一个"空格",在控制台感觉没有什么问题。而在PTA上,可能他的校对方式的局限,最后的一个输出,还要单独写 printf("%d", A[n])。
总结:今天代码写的有点艰难,对大数的处理不太熟练,甚至说在今天之前毫无头绪。在超过了long long 或double类型数据时,就应该通过数组来存储数据了。除此之外,对于数组越界的问题也应该考虑,不然写的代码就有问题。