记:第二次线上赛(一)

1.数的分解

描述
这是一道 Special Judge 的题目,只要输出符合题目要求的答案,那么你的程序就会被认为是正确的。(等等这不是废话吗?!)
给你一个正整数 n,你能否把 n 分解成 一个素数 与 一个合数 的和。

输入
第一行是一个正整数 T 代表测试案例的数量。(1 <= T <= 100000)
每组测试案例是一个正整数 n 。(1 <= n <= 100000)

输出
如果你可以把 n 分解成 一个素数 与 一个合数 的和,那么输出这两个数,并以空格隔开;如果不能,则输出-1。

每组案例输出结束以后都要换行。
样例输入
2
3
11

样例输出
-1
5 6

HINT
把 11 分解成 9 和 2,你的答案也会被认为是正确的。
先输出合数再输出素数不会影响答案的正确性。

代码:

#include<iostream>
#include<cmath>
using namespace std;
bool isPrime(int m)
{
	if (m < 2)
	{
		return false;
	}
	for (int i = 2; i<=sqrt(m); i++)
	{
		if (m % i == 0)
			return false;
	}
	return true;
}
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		int m,a;
		cin >> m;
		if (m <= 5)
		{
			cout << -1;
		}
		else 
		{
			a = m;
			while (m--)
			{
				if (isPrime(m) && !isPrime(a - m)&&(a-m)>1)
				{
					break;
				}
			}
			cout << m << " " << a - m;
		}
		cout << endl;
	}
	return 0;
}

总结:先发现一个事实:若m<6,则不可能找到任何一个满足题意的情况(因为最小的素数为2,最小的和数为4);而若m>=6,则一定能找到一个满足题意的情况。
在循环开始之前,先将m的值赋给a,接着再用循环判断:让m不断地自减1,直到满足m为素数的同时(a-m)为和数的情况break,减少运行时间;同时,应注意和数的判断:(a-m)不为素数且(a-m)的值大于1。

2.约会时间

描述
在数字里,只有0、1、6、8、9倒过来看还是数字,分别变成了0、1、9、8、6。
有一对情侣Alice和Bob用纸条约定明天见面的时间。他们约会的合理时间只会在a点b分到c点d分之间(包含两端)。
Alice写好时间向Bob传递纸条,Bob拿反了,看成了另一个不同的时间。问Alice写的时间有多少种不同的可能性?

已知Alice不会写错时间,并且写的时间一定会在合理时间范围内(a点b分到c点d分之间)
Bob也足够聪明如果有数字反过来根本不是数字,就会发现纸条拿反了,从而不会看错;如果反过来看的时间不在合理时间范围内,也会意识到拿反了纸条,从而不会看错。
Alice和Bob事先有约定,只用时和分来表示时间,而且即使时或分只有一位数,也要在前面补0成两位数;并且用24小时制的时间(从00:00到23:59)。
例如下午3点5分,他们会表示成15:05;凌晨0点8分,他们会表示成00:08。

输入
4个整数a、b、c、d,含义见【描述】。
保证a点b分和c点d分是24小时制的合法时间,而且c点d分一定是a点b分之后的时刻。

输出
一个整数,表示Alice有多少种合理的时间写法。
不要换行。

样例输入
11 8 11 12

样例输出
0

HINT
样例中,11:08到11:12之间,11:08倒过来是80:11不是合法时间;11:09倒过来是60:11不是合法时间;11:10倒过来是01:11是合法时间,但不在11:08到11:12之间;11:11倒过来是11:11是合法时间也在11:08到11:12之间,但与原时间一样,不满足倒过来是不同时间的要求;11:12倒过来不是数字。所以都不满足要求。

代码:

#include<iostream>
#include<cmath>
using namespace std;
int f(int a)//返回一个数翻转后的结果
{
	string a1;
	while (a > 0)
	{
		a1 += a % 10 + '0';
		a /= 10;
	}
	if (a1.length() < 2)
	{
		a1 = a1+'0';
	}
	int ans = 0;
	for (int i = 0; i < a1.length(); i++)
	{
		ans += (a1[i]-'0')*pow(10 , a1.length() - 1 - i);
	}
	return ans;
}
bool isLegaltime(int a, int b)
{
	if (a == 0)
	{
		if (b == 1)
			return true;
		else if (b == 10)
			return true;
		else if (b == 11)
			return true;
		else
			return false;
	}
	else if (a == 1)
	{
		if (b == 0)
			return true;
		else if (b == 1)
			return true;
		else if (b == 11)
			return true;
		else
			return false;
	}
	else if (a == 10)
	{
		if (b == 0)
			return true;
		else if (b == 10)
			return true;
		else if (b == 11)
			return true;
		else
			return false;
	}
	else if (a == 11)
	{
		if (b == 0)
		{
			return true;
		}
		else if (b == 1)
		{
			return true;
		}
		else if (b == 10)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	return false;
}
int main()
{
	int a, b, c, d, cnt = 0;
	cin >> a >> b >> c >> d;
	int start = a * 60 + b, end = c * 60 + d;
	while (a==c&&b<=d||a<c)
	{
		if (isLegaltime(a, b))
		{
			int a1 = f(b), b1 = f(a);
			if (a1 * 60 + b1 >= start && a1 * 60 + b1 <= end)
			{
				cnt++;
				//cout << "符合时a=" << a << " " << "b=" << b << endl;
				//cout << "翻转后a1=" << a1 << " " << "b1=" << b1 << endl;
				//cout << endl;
			}
		}
		b++;
		if (b > 60)
		{
			a++;
			b = 0;
		}
		//cout << "a=" << a << " " << "b=" << b << endl;
	}
	cout << cnt;
	return 0;
}

3.广播操

描述
广播操的口令是12345678 22345678 32345678 … 82345678,然后下一节继续这样的循环,就像是一个无线循环的数列。好奇的火华想知道这个无穷无尽的数列中的第x个数字是几。
输入
一个正整数n,表示测试案例的数量。
每组案例由一个正整数x组成,x不大于1e+9,含义见【描述】。

输出
针对每组案例,输出一个一位整数,表示数列第x个数字。
每组案例输出完都要换行。

样例输入
2
10
65

样例输出
2
1

HINT
第10个数字是22345678中的第二个2,第65个数字是第二轮循环中12345678的数字1。

代码:

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		int m;
		cin >> m;
		if (m > 64)
		{
			m %= 64;
		}
		if (m % 8 == 1)
		{
			cout << m / 8 + 1;
		}
		else if (m % 8 == 0)
		{
			cout << 8;
		}
		else
		{
			cout << m % 8;
		}
		cout << endl;
	}
	return 0;
}

总结:要点就在于将大于64的数字变为64以内的数字
即:若m>64,则应立刻让m对64取模,使m的范围永远在64这一个循环内,这是最重要的!
其次便是找规律:若m是8的倍数,则则输出8;若m对8取模的结果为1,则输出m/8+1;其他则是输出m对8取模的结果。
因此,以后做到类似题目——在某一个范围内规律变化的数列,第一步便是要控制m的值在循环范围之内!

4.平方和

描述
已知一个正整数x,问x能否凑成三个互不相同的正整数的平方和。

输入
一个正整数n,表示测试案例的数量。
每组案例由一个正整数x组成(x不大于1e+8)。

输出
针对每组案例,如果x可以表示成三个互不相同的正整数的平方和,那么输出Yes,否则输出No。
每组案例输出完都要换行。

样例输入
2
30
10

样例输出
Yes
No

#include<iostream>
#include<cmath>
using namespace std;
bool f(int x)
{
	for (int i = 1; i * i <= x / 3; i++)
	{
		for (int j = i + 1; j * j <= (x - i * i) / 2; j++)
		{
			int m = x - i * i - j * j;
			int k = sqrt(m);
			if (k * k == m)
			{
				return true;
			}
		}
	}
	return false;
}
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		int x;
		cin >> x;
		if (f(x))
			cout << "Yes";
		else
			cout << "No";
		cout << endl;
	}
	return 0;
}
        

5.等差数列

描述
已知等差数列的前三项,问数列中首个值大于x的项是第几项?

输入
一个正整数n,表示有n组测试案例。
每组案例由4个整数a、b、c、x表示,范围均在-5e+8到5e+8之间。
其中a、b、c是数列中的第1项、第2项、第3项。x的含义见【描述】。

输出
针对每组案例,输出一个整数y,表示数列中首个值大于x的项是第y项。如果数列中没有任何项能大于x,则输出-1。
每组案例输出完都要换行。

样例输入
3
4 5 6 7
9 7 5 10
10 20 30 15

样例输出
5
-1
2

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		long long int a, b, c,x;
		cin >> a >> b >> c>>x;
		if (x >= a)
		{
			if (a - b >= 0)
			{
				cout << -1;
			}
			else
			{
				cout << (x + 2 * b - 3 * a) / (b - a);
			}
		}
		else
		{
			cout << 1;
		}
		cout << endl;
	}
	return 0;
}      

总结:先判断x的值是否大于首项:若x<a,则直接输出1(因为此时首项a就是第一个大于x的项);若x>=a,分为递增与递减两种情况:若为递减数列,因为第一项就小于x,所以永远也不可能有一项大于x,此时直接输出-1;若为递减数列,则应通过方程x+(b-a)=a+(n-1)*(b-a)得到n的通项公式,获得第一位大于x的项所对应的项数。

6.吐泡泡

描述
小鱼儿,吐泡泡,吐了 n 个小泡泡。我们规定这些小泡泡的大小都是 1 ,并且每两个大小相同的泡泡都可以合成一个更大的泡泡,例如:两个大小为 1 的泡泡可以变成一个大小为 2 的泡泡,两个大小为 2 的泡泡可以变成一个大小为 4 的泡泡,…,以此类推。现在我想知道这 n 个小泡泡最后会变成多少个泡泡。

输入
第一行是一个正整数 T 代表测试案例的数量。(1 <= T <= 1e5)

从第二行到第 T+1 行,每行有一个正整数 n 代表小鱼儿吐了 n 个小泡泡。(1 <= n <= 1e18)

输出
针对每组案例,输出这 n 个小泡泡最后会变成多少个泡泡,然后换行。

样例输入
2
5
8
样例输出
2
1

HINT
5个小泡泡最后会变成一个大小为 4 的泡泡和一个大小为 1 的泡泡。
8个小泡泡最后会变成一个大小为 8 的泡泡。

#include<iostream>
using namespace std;
int main()
{
	long long int n;
	cin >> n;
	while (n--)
	{
		long long int a,cnt=0;
		cin >> a;
		while (a)
		{
			if (a % 2 != 0)
			{
				cnt++;
			}
				a /= 2;
			
		}
		cout << cnt << endl;
	}
	return 0;
}

总结:找规律——当泡泡的总数为奇数时,总有一个泡泡无法与其他泡泡合并,而其他的泡泡每两个合并,因此泡泡的总数就成为原来的一半;若泡泡为偶数,则最后一定只能合成一个泡泡。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值