新生选拔赛一

A 传送门:noj 2066

        简单的求和输出,只是和为0时输出字符串。

        不过比赛过程中出现了一个没想到的问题,大家输出数字时注意到输出回车了,可是却忘了字符串时的回车,大家有经验之后就不会犯这样的问题了

/******************************************************
 * File Name:   2066.cpp
 * Author:      kojimai
 * Create Time: 2014年11月13日 星期四 13时09分38秒
******************************************************/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
int main()
{
	int keng,a,b,c,d;
	scanf("%d",&keng);
	while(keng--)
	{
		scanf("%d%d%d%d",&a,&b,&c,&d);
		int ans = a + b + c + d;
		if(ans == 0)
			printf("sidajiekong\n");
		else
			printf("%d\n",ans);
	}
	return 0;
}


B 传送门:noj 2063

        题意:从一个数组中找出三个数,使得它们能够构成一个三角形,且构成的三角形的周长最大。

        

        贪心题,给数组排序之后,从最大数开始枚举,每一次都选择当前能选到的和最大的三个数,然后判断这三个数是否能构成三角形,若能则这个三角形的周长就是答案了。若直到最后都找不到三个能构成三角形的数则输出-1即可

/******************************************************
 * File Name:   2063.cpp
 * Author:      kojimai
 * Create Time: 2014年11月13日 星期四 13时17分45秒
******************************************************/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define FFF 23
int a[FFF];

int main()
{
	int keng;
	scanf("%d",&keng);
	while(keng--)
	{
		int n;
		scanf("%d",&n);
		for(int i = 0;i < n;i++)
			scanf("%d",&a[i]);
		sort(a,a+n); // 这是一个系统函数,实现从小到大的排序
		int ans = -1;//还没有找到可行解时给答案赋值为-1
		for(int i = n-1; i > 1 && ans == -1 ;i--)
		{
			for(int j = i - 1;j > 0 && ans == -1;j--)
			{
				for(int k = j - 1;k >= 0 && ans == -1;k--)
				{
					if(a[j] + a[k] > a[i])
					{
						ans = a[j] + a[k] + a[i];
					}
				}
			}
		}
		//找到可行解时ans==-1的条件不再满足因此退出循环
		printf("%d\n",ans);
	}
	return 0;
}


C 传送门:noj 2070

        题意:第一秒有一只兔子,这只兔子每一秒都会生出一只兔子,然后新出生的兔子在出生后的第4秒开始每秒也会生一只兔子,问指定时间有多少只兔子


        斐波那契数列的变形题,这里我用递推的方式写

        因为最多只问到第55秒,所以我们可以直接先求出这55秒的结果,然后按输入直接输出

        处理方法:

        ①暴力递推:

                          第一只兔子从第二秒开始每一秒都会生一只兔子,

                          后来新出生的兔子从出生的第4秒开始直到最后每秒都会生一只兔子,

                          于是我们可以计算每一秒有多少兔子新出生,并处理出这些新出生的兔子在之后的时间内生的新兔子,最后求和即可

/******************************************************
 * File Name:   2070.cpp
 * Author:      kojimai
 * Create Time: 2014年11月13日 星期四 13时29分50秒
******************************************************/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define FFF 55
int a[FFF];//存每一秒的兔子总和
int b[FFF];//存每一秒新生出的兔子数量
void init()
{
	memset(b,0,sizeof(b));
	a[1] = 1;
	for(int i = 2; i <= 55;i++)
		b[i] = 1;//第一只兔子在每一秒都会新生出一只兔子
	for(int i = 2; i <= 55;i++)
	{
		a[i] = a[i-1] + b[i];
		for(int j = i + 3; j <= 55;j++)
		{
			b[j] += b[i];//这一秒出生的兔子在之后的时间内生的兔子,加到那一秒新出生的兔子数量上
		}
	}
	return;
}

int main()
{
	init();
	int keng;
	scanf("%d",&keng);
	while(keng--)
	{
		int n;
		scanf("%d",&n);
		printf("%d\n",a[n]);
	}
	return 0;
}

        ② 斐波那契数列版:

                      不强求大家理解,看看吧 递推公式 a[i] = a[i-1]+a[i-3]

/******************************************************
 * File Name:   2070_2.cpp
 * Author:      kojimai
 * Create Time: 2014年11月13日 星期四 13时45分54秒
******************************************************/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define FFF 55
int a[FFF];
void init()
{
	a[1] = 1;
	a[2] = 2;
	a[3] = 3;
	a[4] = 4;
	for(int i = 5;i <= 55;i++)
		a[i] = a[i-1] + a[i-3];
}
int main()
{
	init();
	int keng,n;
	cin>>keng;
	while(keng--)
	{
		cin>>n;
		cout<<a[n]<<endl;
	}
	return 0;
}

D 传送门: noj 2071

        题意:就是题目所说,把数字码转换成HDB3码,

  

        出题人的恶趣味,就是模拟处理,考验大家的代码水平。处理方法:

        首先,从头到尾扫一边,把所以的1分别变为+1,1。

        然后再扫一边,找出所有的4连零,把对应位置变成+V,-V。(正负号根据前面最靠近的的1正负号定)

        最后再扫一边,需要一个标识符号,表示当前的符号需不需要变化。假如有两个相邻的V中间有偶数个1,则改为B00V,符号依情况而定,且标识符取反,奇数则不变,然后根据标识符继续向后扫

/******************************************************
 * File Name:   hdb3.cpp
 * Author:      kojimai
 * Create Time: 2014年10月30日 星期四 13时03分29秒
******************************************************/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define FFF 105
int a[FFF];
void print(int x) 
{
	switch(x)//根据对应的数输出对应的符号
	{
		case 0:cout<<0;return;
		case 1:cout<<"+1";return;
		case 2:cout<<"+V";return;
		case 3:cout<<"+B";return;
		case -1:cout<<"-1";return;
		case -2:cout<<"-V";return;
		case -3:cout<<"-B";return;
	}
}
int main()
{
	int n;
	cin>>n;
	for(int i = 1;i <= n;i++)
		cin>>a[i];
	bool flag = false; //记录下一个1的符号 false(即0) 表示 下一个1为 -1  true(即1)  表示下一个1为 +1
	for(int i = 1;i <= n;i++)
	{
		if(a[i] == 1)
		{
			if(flag)
			{
				flag = false;
			}
			else
			{
				a[i] = -1;
				flag = true;
			}
		}
	}
	int cnt = 0;//记录当前访问到的连0的个数
	for(int i = 1;i <= n;i++)
	{
		if(a[i] == 0)//遇到0 cnt值加1
		{
			cnt++;
			if(cnt == 4)//遇到四连零则变化
			{
				if(flag)//依据最靠近的1的符号确定V的符号
					a[i] = 2;//2表示+V
				else
					a[i] = -2;//-2表示-V
				cnt = 0;//清零
			}
		}
		else if(a[i] == 1)
		{
			cnt = 0;
			flag = true;//表示下一次遇到4连零时需要改为+V
		}
		else
		{
			flag = false;//下一次遇到4连零时改为-V
			cnt = 0;
		}
	}
//	for(int i = 1;i <= n;i++)
//		cout<<a[i]<<" ";cout<<endl;
	bool turn = false,first = true;
	cnt = 0;
	for(int i = 1;i <= n;i++)
	{
		if(a[i] == -2 || a[i] == 2)
		{
			if(first)//第一个4连零不需要改为B00V
			{
				first = false;
				cnt = 0;
				continue;
			}
			if(turn)//根据反型符号进行变化
			{
				a[i] = -a[i];
			}
			if(cnt % 2 == 0)//cnt表示相邻的两个V之间1的个数
			{
				//为偶数时
				if(a[i] == 2)//当前V为+V时 这一段000+V 要变成 -B00-V
				{
					a[i-3] = -3;//-3表示-B
					a[i] = -2;//-2表示-V
				}
				else//V为-V时
				{
					a[i-3] = 3;//+B
					a[i] = 2;//+V
				}
				turn = !turn;//标识符
			}
			cnt = 0;
		}
		else if(a[i] == 1 || a[i] == -1)
		{
			if(turn)//遇到1需要反型
				a[i] = -a[i];
			cnt++;
		}
	}
	for(int i = 1;i <= n;i++)
	{
		print(a[i]);
		if(i<n)
			cout<<' ';
		else
			cout<<endl;//c++的回车符
	}
	return 0;
}

E 传送门: noj 2068

        题意:超出给定的数组可以找多少不同的连续子串,使得子串中的任意两个数不能相等。(这里的不同只需要满足位置不同就好)

 

        简单来想就是找两个点(l,r),使得这两个点范围内的所有数都不想等,找出这样的点对有多少个

        我们可以这样做,从左往右扫,记录一个left表示到位置i为止,最小的left使得left+1到i-1位置上所有的数都不相同

        然后新加来第i个数,

            ①如果这个数和left+1到i-1的数都不相同,那么以i为有端点,以left+1到i为左端点的所有子串都可以,因此统计的答案加上 i-left

            ②如果这个数和left+1到i-1范围内的某个数相同了,那么就需要更新left使得left满足①的要求,把left更新成第i个数最后一次出现的位置即可。(原因大家思考一下)

/******************************************************
 * File Name:   2068.cpp
 * Author:      kojimai
 * Create Time: 2014年11月13日 星期四 14时09分48秒
******************************************************/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define FFF 1000005
int a[FFF],last[FFF];//last数组记录每一个数最后一次出现的位置,0表示没有出现过
int main()
{
	int keng;
	scanf("%d",&keng);
	while(keng--)
	{
		int n;
		scanf("%d",&n);
		for(int i = 1;i <= n;i++)
			scanf("%d",&a[i]);
		memset(last,0,sizeof(last));
		int ans = 0,left = 0;
		for(int i = 1;i <= n;i++)
		{
			if(last[a[i]] > left)//a[i]和left+1~i-1中的某个数重复了,则需要更新left值
				left = last[a[i]];
			ans += i - left;
			last[a[i]] = i;
		}
		cout<<ans<<endl;
	}
	return 0;
}

F 传送门: noj 2069

       题意:判断给定的三个数的素因子集合是否相同


       首先求出这三个数的最大公约数,然后每个数都进行如下操作

       ①和最大公约数求新的公约数,并除以它

       ②新的公约数为1或者,数本身变为1,则停止,否则重复①操作

       到最后如果三个数都变为1,则说明这三个数素因子集合相同

/******************************************************
 * File Name:   2069.cpp
 * Author:      kojimai
 * Create Time: 2014年11月13日 星期四 14时24分46秒
******************************************************/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;

int gcd(int x,int y)//辗转相除法求最大公约数,不懂请自行查找介绍
{
	int b;
	while(y)
	{
		b = y;
		y = x % y;
		x = b;
	}
	return b;
}

int solve(int x,int t)//这个三个数跟原来的公约数不断求新的公约数并除以新的公约数使得数不断缩小,直到新的公约数为1或者原来的数变为1
{
	while(x>1)
	{
		int y = gcd(x,t);
		if(y==1)
			break;
		x = x / y;
	}
	return x;
}

int main()
{
	int keng;
	scanf("%d",&keng);
	while(keng--)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		int t = gcd(a,b);
		t = gcd(t,c);//求出三个数的最大公约数
		a = solve(a/t,t);
		b = solve(b/t,t);
		c = solve(c/t,t);
		if(a == 1 && b == 1 && c == 1)
			printf("YES\n");
		else
			printf("NO\n");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蓝桥杯是中国著名的计算机竞之一,包括蓝桥杯全国软件和信息技术专业人才大以及蓝桥杯全国青少年程序设计比。其中,蓝桥杯python选拔赛是为了选拔具有优秀python编程能力的参者而举办的事。 蓝桥杯python选拔赛注重考察参者对python语言的理解和应用能力。在比中的题目往往涵盖了python编程的各个方面,包括基本语法、数据结构、算法设计和程序设计思维等。选手需要在规定的时间内,按照题目要求,使用python语言编写解决方案。 参加蓝桥杯python选拔赛可以提高参者的编程能力和解决问题的能力。通过参加比,选手们可以接触到各种不同类型的编程题目,锻炼自己的编程思维和动手能力。同时,比还提供了一个交流和学习的平台,选手们可以与其他参者分享经验、学习别人的优秀解法,提高自己的编程水平。 此外,蓝桥杯python选拔赛还是选拔参加蓝桥杯全国软件和信息技术专业人才大的入场券。优秀的选手将有机会代表自己的学校或单位参,并在比中展示自己的才华。 总之,蓝桥杯python选拔赛是一个提高编程水平、展示自己才能的良好平台。参加比不仅可以锻炼自己的编程能力,还可以结识其他编程爱好者,促进学习和交流。相信通过努力和参与,每个选手都能在蓝桥杯python选拔赛中获得进步和收获。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值