本周的算法题(来自CF)

在本周博主做的四道算法题中选出两道算法题进行思路的讲解(仅仅是一种解题方式),博主的代码有点多,如有更好的解题思路或代码,欢迎发到评论区

1.Candies

本题意思是:有两种法术,一种是2x+1,一种是2x-1,初始的糖果数目为1,输入你想获得的糖果数目,如果能通过有限次(<=40) 的法术来获得需要数目的糖果,先输出使用的法术次数,在换行依次输出使用的是哪个法术;若不能的到所需的糖果数目,就输出-1

大体思路
无论是法术1还是法术2,只能获得数目为奇数的糖果,数目为偶数时,输出-1
对于奇数的糖果进行法术的分配,列两个方程,2x-1和2x+1,哪个法术算出x为奇数,则用的哪个法术

注意事项

由于我们是从后往前算的,所以计算出的法术顺序是反的,需要从前向后输出才是正确的

现在我们开始逐步实现代码

#include<iostream>
#include<vector>
using namespace std;

int main()
{
//我们需要的几个测试对象
	int n = 0;
	cin >> n;

//法术1
	int count1 = 0;

//法术2
	int count2 = 0;
	int y = 0;

//elem存放我们需要的糖果数目
	vector<int>elem;

//pell存放达到所需数目糖果的法术
	vector<int>pell;

//count存放我们使用法术的次数
	vector<int>count;

//输入我们需要的糖果数目,将其依次插入elem中
	for (int i = 0; i < n; i++)
	{
		int candies = 0;
		cin >> candies;
		elem.push_back(candies);
	}
}

博主实现法术1的方式是

((j + 1) / 2) % 2 != 0

法术2

((j - 1) / 2) % 2 != 0

需要注意的是当j=2时,式子也成立,所以还需要加入限制条件

如果式子成立,就将1或者2插入pell中

for (j = elem[i]; j > 1;)
		{
			if (((j + 1) / 2) % 2 != 0 && j % 2 != 0)
			{
				j = (j + 1) / 2;
				pell.push_back(1);
				count1++;
			}
			else if (((j - 1) / 2) % 2 != 0 && j % 2 != 0)
			{
				j = (j - 1) / 2;
				pell.push_back(2);
				count2++;
			}
			else if (j % 2 == 0)
				break;
		}

接下来开始判断糖果的数目是否能用法术1和法术2表示

因为我们的count是一个连续的数列,为了不影响操作,当糖果的数目为偶数的时候,将0插入

这里有一个坑,如果我们不管这个偶数糖果的count,如果输入中间有零的糖果数,就会出现错误,如:3,4,5,6,7,8,9

if (elem[i] % 2 == 0)
		{
			count.push_back(-1);
			cout << count[i] << endl;
			count[i] = 0;
		}
		else
		{
            count.push_back(count1 + count2);
	        cout << count[i] << endl;
			int y = 0;
			for (int a = 0; a < i; a++)
			{
				y += count[a];
			}
			if (i == 0)
			{
			    for (int x = count[i]-1; x>=0 ; x--)
                  cout << pell[x] << " ";
				cout << endl;
			}
			else
			{
				if(i==1)
                    y = count[0];
				int x = count[i] + y - 1;
				for (x; x >= y; x--)
					cout << pell[x] << " ";
				cout << endl;
			}
	        
		}

需要注意的是,y的值应该在x的前面被赋予

2.Lucky Numbers

 题目大意:给定两个数,在这个区间内,将所有数中的最大数字和最小数字相减,输出差值最大的那个数

思路:将一个数字拆分,用%10后/10的操作来实现,求出最大数字和最小数字,将两个数字的差值存入容器中,使用find函数返回最大值的下标,便于我们输出原数

我们使用了max_element和min_element,它们是<algorithm>中的库函数,用于返回最大值和最小值的地址max_element(begin,end)

#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{
	int n(0);
	cin >> n;
	int f = 0;
	int l = 0;
	vector<int>array;
	vector<int>first;
	vector<int>last;
	vector<int>all;
	vector<int>a;//存储最大数字和最小数字的差值
	for (int i = 0; i < n; i++)
	{
		cin >> f;
		first.push_back(f);
		cin >> l;
		last.push_back(l);
	}
	int m = 0;
	for (int j = 0; j < n; j++)
	{
		m = 0;
		for (int i = first[j]; i <= last[j]; i++)
		{
		   all.push_back(i);
		   int d = i;
	       while (d > 0)
	       {
		       array.push_back(d % 10);
		       d /= 10;
	        } 
		   int max = *max_element(array.begin(), array.end());
		   int min = *min_element(array.begin(), array.end());
		   a.push_back(max - min);
		   array.clear();
		   m++;
		}
		int max = *max_element(a.begin(), a.end());
		int c = find(a.begin(), a.end(), max) - a.begin();
		cout << all[c] << endl;
		all.clear();
		a.clear();
		//b.clear();
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值