2022-04-25每日刷题打卡

本文介绍了两道编程题目,第一题涉及将给定长度的字母序列按特定规则转换为倒数第N个字符串,第二题讨论如何通过加一或乘二操作使整数变为零的最小步骤。这两题都考察了数学和算法思维,第一题利用26进制转换,第二题通过枚举和位运算找到最短路径。
摘要由CSDN通过智能技术生成

2022-04-25每日刷题打卡

代码源——每日一题

倒数第n个字符串 - 题目 - Daimayuan Online Judge

给定一个完全由小写英文字母组成的字符串等差递增序列,该序列中的每个字符串的长度固定为 L,从 L 个 a 开始,以 1 为步长递增。例如当 L 为 3 时,序列为 aaa,aab,aac,…,aaz,aba,abb,…,abz,…,zzz。这个序列的倒数第 2 个字符串就是 zzy。对于任意给定的 L,本题要求你给出对应序列倒数第 N 个字符串。

输入格式

输入在一行中给出两个正整数 L (2≤L≤6)和 N( N≤10^5).

输出格式

在一行中输出对应序列倒数第 N 个字符串。题目保证这个字符串是存在的。

样例输入
6 789
样例输出
zzzyvr

这题其实和进制转化差不多,把一个数转化成26进制的数,0~25对于26个字母。

但是直接转进制是有问题的,因为前置条件有两种,一种是在他给的长度为基础上算,比如这里给的长度L是6,那就是以aaaaaa的基础来算,第二点他给的是倒数的顺序而不是正数。

其实很好办,既然是倒数,我们直接求出最末尾一位的字符串转化成10进制的样子,比如这里长度L是6,最后一位应该是zzzzzz,这是倒数第1个字符串,然后我们要算倒数第N,就用这个数减去N+1即可。再用得到的数通过进制转换求出字符串。

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>

#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50;

int main()
{
	int l, n;
	cin >> l >> n;
	ll ans = pow(26, l);
	
	ll res = ans - n;
	string s;
	if (res == 0)
	{
		for (int i = 0; i < l; i++)s += 'a';
	}
	else
	{
		while (res)
		{
			s = (char)(res % 26 + 'a') + s;
			res /= 26;
		}
	}
	cout << s << endl;
	return 0;
}

CodeForces

Problem - 1661B. Getting Zero

Suppose you have an integer v. In one operation, you can:

either set v=(v+1)mod32768
or set v=(2⋅v)mod32768.
You are given n integers a1,a2,…,an. What is the minimum number of operations you need to make each ai equal to 0?

Input

The first line contains the single integer n (1≤n≤32768) — the number of integers.

The second line contains n integers a1,a2,…,an (0≤ai<32768).

Output

Print n integers. The i-th integer should be equal to the minimum number of operations required to make ai equal to 0.

Example
input

4
19 32764 10240 49

output

14 4 4 15 

Note

Let’s consider each ai:

a1=19. You can, firstly, increase it by one to get 20 and then multiply it by two 13 times. You’ll get 0 in 1+13=14 steps.
a2=32764. You can increase it by one 4 times: 32764→32765→32766→32767→0.
a3=10240. You can multiply it by two 4 times: 10240→20480→8192→16384→0.
a4=49. You can multiply it by two 15 times.

这题是说,给你n个数,你可以对一个数进行两种操作,一个是把数+1后%32768,一个是把数*2后%32768,问你经过多少步操作可以把一个数变成0。

首先我们已经可以看出了,想把一个数变成0,相当于把这个数变成32768的倍数,然后一个热知识:2^15==32768。也就是说,只要你这个数不是0,那么我们最多15步就可以把你变成0,只要选操作2选15次就行。然后现在有个问题,如果混上了操作1,那最简能是多少步呢?这里我们可以依靠枚举来做,因为最多进行15次操作就可以把一个数变成0,我们枚举这个数从1加到15,加操作后就逐步算*2的操作,要是能在两者操作数相加等于15前把这个数变成0,我们就维护一下这个操作数,如果等于15了还没变0,我们也没必要继续算下去了,这样我们就可以在时间复杂度O(15n)的情况下算出所有数的操作数.

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>

#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50;

int main()
{
	int n;
	cin >> n;
	vector<int>v(n), p(16);
	p[0] = 1;
	for (int i = 1; i <= 15; i++)
	{
		p[i] = p[i - 1] * 2;
	}
	for (int i = 0; i < n; i++)cin >> v[i];
	for (int i = 0; i < n; i++)
	{
		if (v[i] == 0)
		{
			cout << 0 << " ";
			continue;
		}
		int res = 15;
		for (int j = 0; j <= 15; j++)
		{
			int ans = v[i] + j;
			for (int k = 0; k <= 15 - j; k++)
			{
				if (ans * p[k] % 32768 == 0)
				{
					res = min(res, j + k);
					break;
				}
			}
		}
		cout << res << " ";
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值