2020-12-18日 去年期末真题

第二题:

在这里插入图片描述
sin(x)可以看成是数列an=(-1)n-1*x2n-1/(2n-1)!的前n项和。
遇到这种式子,我们可以观察到

二题方法一(a迭代):

思路

当n >= 2 时 :an = -an-1*x2/(2n-2)/(2n-1);
当n = 1 时 :a1 = x;
得知了第n项与第n-1项的关系,而且要求的是每一项的和,所以我们可以让a迭代求和。

#include <stdio.h>

int main()
{
	double x;
	int n,i;
	scanf("%lf%d",&x,&n);
	double a = x;
	double sum = x;
	for(i = 2 ; i <= 2 * n - 1 ; i += 2)
	{
		temp *= -x * x / i / (i + 1);//进行迭代
		sum += temp;
	}
	printf("%.4lf\n",sum);
	return 0;
}

二题方法一(求每一项(室友的方法)):

思路

因为我们知道了an=(-1)n-1*x2n-1/(2n-1)! ,所以我们可以将数列的每一项都求出来。在知道数列的通项公式的时候可以首先想到把每一项都求出来。

#include <stdio.h>
#include <math.h>

int main()
{
	double x,sum = 0.0;
	int n;
	scanf("%lf%d",&x,&n);
	double temp = 1.0;//小心temp超出范围哦,阶乘是很大的哦。
	int i;
	for(i = 1;i <= 2 * n - 1;++i)
	{
		temp *= i;
	}
	++n;//因为进入while先执行n--使n减一,所以先++n;
	while(n--)
	{
		sum += pow(-1,n-1)*pow(x,2*n-1)/temp; 
		temp /= (2*n-1)/(2*n-2);
	}
	printf("%.4lf\n",sum);
	return 0;
}

第五题:

在这里插入图片描述在这里插入图片描述

五题解法一(排序):

思路(来自可爱的组员)

因为它要按字符串的长度升序输出,所以我们可以排个序。

#include <stdio.h>
#include <string.h>

int main()
{
	int n,i;
	char a[100][101];
	scanf("%d",&n);
	getchar();//scanf后面会有一个/n哦,把它getchar掉
	for(i = 0;i < n;i++)
	{
		gets(a[i]);
	}
	int j;
	for(i = 0;i < n - 1;++i)
	{
		for(j = i + 1;j < n;++j)
		{
			if(strlen(a[i]) > strlen(a[j]))
			{
				char s[101];
				strcpy(s,a[j]);
				strcpy(a[j],a[i]);
				strcpy(a[i],s);
			}
		}
		//这个循环结束出来,a[i]是在i后最短的字符串;
		puts(a[i]);
	}
	puts(a[n-1]);//因为是i==n-1的时候退出了循环,但是a[n-1]还未输出
	return 0;
}

五题解法二(标记)

思路

曾经在做字符串去重的时候,我们用过字符串标记法,但是标记了的含义仅仅只代表了字符是否出现过;由这个为基础而拓展,我们可以把标记的数字也赋予含义,先附上代码。
我们是想要让从短到长输出字符串,所以我们可以用一个数组来标记,它的下标代表长度,它的数值代表这个长度的字符串出现的位置:设num[i] = x 那么字符串长度为i的字符串为a[j]

#include<stdio.h>
#include<string.h>

int main()
{
	char a[100][101];
	int n,i;
	scanf("%d",&n);
	getchar();//scanf后面会有一个/n哦,把它getchar掉
	char num[101];
	memset(num,-1,101);
	for(i = 0; i < n; i++)
	{
		gets(a[i]);
		num[strlen(a[i])] = i;
	}
	for(i = 0;i<101;i++)
	{
		if(num[i] != -1)
		{
			puts(a[num[i]]);
		}
	}
	return 0;
}

第七题

在这里插入图片描述在这里插入图片描述

七题解法一(暴力匹配法):

思路

遇到不匹配即回溯(附图)

从主串和字串的头开始(即i=0;j=0)
在这里插入图片描述
发现匹配则让两个都往下挪一个
在这里插入图片描述
发现又匹配 再往下挪
在这里插入图片描述
哟,不匹配了,怎么办呢,咱们就换一个头开始重新对比
这样,咱们就需要找到原先头对着哪里,所以可以整个k做外层循环来做头即下方代码
在这里插入图片描述

#include<stdio.h>
#include<string.h>
int main(void)
{
	char a[100],b[30];
	gets(a);
	gets(b);
	int len1=strlen(a);
	int len2=strlen(b);
	int i,j,k,count=0;
	for(k=0;k+len2<=len1;k++)
	{
		for(i=j,j=0;j<len2;i++,j++)
		{
			if(a[i] != b[j])	break;
		}
		if(j == len2 && a[i] == ' ')	count++;
	}
	printf("%d\n",count);
	return 0;
}

当然,也可以不需要k,我们可以看出来
在这里插入图片描述
之前的头为i-j+1;所以发生不匹配可以让i = i - j +2; j = 0;
这样二层循环可以写成一层循环判断出循环条件为i+len2<=len1即可

七题解法一(KMP算法):

思路

这个的思路是优化了一下上方暴力算法,上方暴力算法是发生不匹配的时候 让i回溯(就是让i回到原先的值),而KMP算法可以让i不回到原先的值,这个算法过几天我会写个算法分析,这个你们可以先看看(有点儿不好理解)

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

void get_next(char s[],int next[])
{
    int i=0;
    int j=-1;
    next[0]=-1;
    int len=strlen(s);
    while(i<len-1)
    {
        if(j==-1||s[i]==s[j])
        {
			if(s[++i] == s[++j])
			{
				next[i] = next[j];
			}
			else
			{
				next[i] = j;
			}
        }
        else
        {
            j=next[j];     
        }
    }
}
int KMP(char s1[],char s2[])
{
    int i=0;
    int j=0;
    int count = 0;
    int len1=strlen(s1);
    int len2=strlen(s2);
    int *next = NULL;
	next = (int *)malloc((len2)*sizeof(int));
	get_next(s2,next);
    while(i<len1)
    {
    	if(j == len2)
    	{
    		if(s1[i] == ' ')
    		{
    			count++;
    			j = -1;
			}
    		else
    		{
    			j = -1;
			}
		}
        if(j == -1 || s1[i] == s2[j])
        {
            i++;
            j++;
        }
        else
        {
            j=next[j];
        }
    }
    free(next);
    return count;
}

int main()
{
	char s1[100];
	gets(s1);
	char s2[31];
	gets(s2);
	printf("%d\n",KMP(s1,s2));
	return 0;
}

其实这类字符串匹配的有好多种算法,KMP只是其中不好用还慢的一种,但它是我们以后要学的算法,我想有时间再写个Sunday算法(好用还快

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值