2021/10/09码加加模拟赛Day3

A.题斐波那契 

解题思路 

水题,打表解决,递归最后一组测试样例会超时。还有大家读题的时候看一下数据范围啊,忽略了不就没分了?

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
	cin>>n;
	int f[40];
	f[0]=0;
	f[1]=1;
	for(int i=2;i<40;i++)  //打表,先把数据范围内的所有数据算出来。
	{
		f[i] = f[i-1]+f[i-2];
	}
	cout<<f[n-1]<<endl;
	return 0;
} 

B.哥德巴赫 

解题思路 

这个和杭电acm中的分拆素数和类似,主要是别超时。

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int p[1000005];
int prime(int n)//求n是否为素数,除1外,不能被1和自己本身之外的数整除的数就是素数
{
	if(n==2)return true;
	for(int i=2;i<=sqrt(n);i++)//遍历到n的平方就够了,这样算能快一点。
	{
		if(n%i==0)return false;
	}
	return true;
}
int main()
{
	int n;
	p[0]=p[1]=0;
	cin>>n;
	//cout<<"n="<<n<<endl;
	for(int i=2;i<=n;i++)//打表,将2到n的所有素数都算出来
	{
		if(prime(i))
		{
			p[i]=1;
			//cout<<i<<" ";
		}else{
			p[i]=0;
		}
	}//cout<<endl;
	for(int i=2;i<=n/2;i++)
	{
		if(p[i]==1&&p[n-i]==1)//遍历,如果这个数是素数,那就看看n-这个数是不是也是。
		{
			cout<<i<<" "<<n-i<<endl;
			break;
		} 
	}
	return 0;
}

C.碾压

解题思路 

这个题暴力只能得20分,抄了个代码大家看看呀。我是没看懂为啥这样做。

#include<iostream>
using namespace std;
int main()
{
	int k,n;
	cin>>k>>n;
	int a[250],fis[25][25]={0};
	for(int x=1;x<=k;++x)
	{
		for(int r=1;r<=n;r++)
		{
			cin>>a[r];
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=i+1;j<=n;j++)
			{
				fis[a[i]][a[j]]++;
			}
		} 
	}
	int count=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
		//	cout<<fis[i][j]<<" ";
			if(fis[i][j]==k)
				count++;
		}//cout<<endl;
	}
	cout<<count<<endl;
	return 0;
 } 

D. 唯一

解题思路 

 说大实话,这个题目描述写得真的是,应该是满足S任意存在一个长为K的字串T。。。。

其实题目真正含义是求最小的字串长度k,就是比如说上面这个例子。

7
ABCDABC   //S这个字符串长这样,我们从k=1开始遍历,k指的是截取字串的长度
*&&&&&&&&&&&&&&&*//k=1时,从头开始截取,最后截取的字串序列是:'A','B','C','D','A','B','C'
                 //然后对这个序列排序,可以看到,截取的字串有重复的,所以最小k不能取1
A
A
B
B
C
C
D

*****
*&&&&&&&&&&&&&&&*//k=2,也有重复的。。。。
AB
AB
BC                //字串序列:'AB','BC','CD','DA','AB','BC',大家看懂了吧,后面不写啦。
BC
CD
DA

*****
*&&&&&&&&&&&&&&&*//k=3
ABC
ABC
BCD
CDA
DAB

*****
*&&&&&&&&&&&&&&&*//k=4,好的,我们看这个排序后的序列,终于没有重复的了,最小的K就是它了。
ABCD
BCDA
CDAB
DABC

*****
4
n = int(input())
s = input()
k = 1
list_s = []
count_list = 0
for i in range(1,n):  #从k=1开始遍历
    #print("k=",i)
    count=0
    for j in range(n-i+1):
        list_s.append("".join(s[j:j+i])) #截取长度为k的字符串,并把截取的字符串添加到list_s中
    #print(list_s)
    len_list = len(list_s)
    for r in range(len_list):
        count_list = list_s.count(list_s[r])  #看看有没有重复的字符串
        #print(count_list)
        if(count_list == 1):
            count += 1                     #遍历,该字符串没有重复count就加一
    if(count == len_list):                 #要是都没有重复,输出当前k的长度
        print(i)
        break
    #print(list_s)
    list_s = []                            #list_s这个序列存的是当前长度为k的字串序列,
                                           #k改变了,里面存的字串也得改变

E.果汁生产 

 

 解题思路

 水题,注意边界值,比如说桶的容积和果汁量相等的情况。嘤嘤嘤,我的分。。。。

//桶都满的情况,测试样例
10 10
1 1
2 2
#include<iostream>
using namespace std;
int sum[3];
struct J{
	int c;//容积 
	int m;//果汁量 
}j[3];
void dao(int i)
{
	sum[i] = j[i].m+j[(i+1)%3].m;//循环的倒果汁,(i+1)%3,这样就可以循环啦
	if(sum[i] <= j[(i+1)%3].c)//如果,能倒完整
		{
			j[(i+1)%3].m = sum[i];
			j[i].m = 0;
		}
	else{//如果第二个桶装不下了,剩下的果汁倒回原来的桶里
		j[(i+1)%3].m = j[(i+1)%3].c;
		j[i].m = sum[i] - j[(i+1)%3].c;
	}
	
}
int main()
{
	
	for(int i=0;i<3;i++)
	{
		cin>>j[i].c>>j[i].m;
	}
	for(int k=1;k<=99;k++)
	{
		for(int i=0;i<3;i++)//三个桶,循环倒三次
		{
			dao(i);
			//cout<<j[0].m<<" "<<j[1].m<<" "<<j[2].m<<endl;
		}
	}
	dao(0);//循环100次,正好最后剩第一个桶往第二个桶倒(1->2)
	cout<<j[0].m<<endl;
	cout<<j[1].m<<endl;
	cout<<j[2].m<<endl;
	return 0;
}

F.平衡

 解题思路

 看了题解,可以用二维前缀和解决。不过这个只能过3个测试样例,剩下的就超时了,让我再想想。

#include<iostream>
using namespace std;
int cnt[1005][1005]; 
int sum[1005][1005];
int main()
{
	int n,x,y,max_x=0,max_y=0,min_x=0,min_y=0;
	cin>>n;
	cin>>min_x>>min_y;
	max_x=min_x;max_y=min_y;
	cnt[min_x][min_y]=1;
	for(int i=1;i<n;i++)
	{
		cin>>x>>y;
		cnt[x][y]=1;
		if(x>max_x)
			max_x = x;
		if(y>max_y)
			max_y = y;
		if(min_x>x)
		min_x=x;
		if(min_y>y)
		min_y=y;
	}
	for(int i=0;i<=max_x+1;i++)
	{
		for(int j=0;j<=max_y+1;j++)
		{
			sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+cnt[i][j];
			//cout<<sum[i][j]<<" ";
		}//cout<<endl;
	}
	int point[4]={0};
	int a,b,c,d;
	int min_p=n;
	for(int i=min_x-1;i<=max_x+1;i++)
	{
		for(int j=min_y-1;j<=max_y+1;j++)
		{
		//(c,d)-(a,b)
		//(0,0)-(a,b)
		a = i;b = j;
		c = d = 0;
		point[0] = sum[a][b]-sum[a][d-1]-sum[c-1][b]+sum[c-1][d-1];
		//(a,0)-(max_x,b)
		c=i;d=0;a=max_x;b=j;
		point[1] = sum[a][b]-sum[a][d-1]-sum[c-1][b]+sum[c-1][d-1];
		//(0,b)-(a,max_y)
		c=0;d=j;a=i;b=max_y;
		point[2] = sum[a][b]-sum[a][d-1]-sum[c-1][b]+sum[c-1][d-1];
		//(a,b)-(max_x,max_y)
		c=i;b=j;a=max_x;b=max_y;
		point[3] = sum[a][b]-sum[a][d-1]-sum[c-1][b]+sum[c-1][d-1];
		int max=0;
		for(int k=0;k<4;k++)
		{
			if(max<point[k])
			max=point[k];
		}
		if(min_p>max)
		min_p=max;
		}
	}
	cout<<min_p<<endl;
	return 0;
}

官方题解

有的题有好几种解决方法,对于算法优化的时间复杂度比我将的方法要好,大家可以看看。

写在最后 

  大佬的炮灰就是我。。。。不过还是学到很多东西。。。。其他天的题等我慢慢更新。

还有是不是大佬讲题都默认我们的水平跟他一样啊,真不好意思到处宣扬自己菜。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值