11.22原创题总结

U280826 学长的数(1) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/U280826

 这个题目就是一个判断1-n中 转化为二进制之后谁的1最多

首先我们最开始的思路可能是一次一次遍历 每次计算这个数上的1的个数 将它与最大值进行比较

但是显然是不行的 因为题目给的n的范围为10^18次 我们这显然会超时

那我们接下来想有什么简便方法呢?

我们可以计算输入的n转化为二进制的位数,那么个数1最多的那个数一定是(这个位置-1)上最大的数字

比如 6 它的位数为3   那么比他小的最多1个数的数字为 3(11)

8它的位数为4 那么比他小的最多1个数的数字为7(111)

那我们可以每次都往我的数加一个1(在二进制的情况下)

接着将这个数的十进制与我的n进行比较

如果比n小 那么继续我的操作 

如果比n大 那么结束循环 然后将我的最高位上的1给去除 这样就能得到我1个数最多的十进制下的数字了

下面是具体代码

#include<bits/stdc++.h>
using namespace std;
int  main() {
	long long  n; cin >> n;
	long long  a = 1;
	long long sum = 0;
	while (sum <= n) {
		sum += a;
		if (sum > n) break;
		a *= 2;
	}
	cout << sum - a;
	return 0;
}

U280869 学长的数(2) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/U280869

这个题目在上一个题目的条件下加了一个新的条件 就是在相同情况下 我要输出尽可能大的数字

 这题我们可以这么想 输入一个n 计算出它的位数k 然后我们放k个1 

之后我们从尾向前,依次将某位上的1个去除换成0 然后将这个数与n进行比较 如果小了 那么就是我们符合的最大的数字

具体代码为:

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>

using namespace std;

int main()
{
	long long  n; cin >> n;
	long long  a = 1;
	long long sum = 0;
	while (sum <= n) {
		sum += a;
		if (sum > n) break;
		a *= 2;
	}
	a *= 2;
	a--;
	for (int i = 0; i < 62; i++) {
		long long p = 1ll << i;
		if (a - p <= n) {
			cout << a - p<<endl;
			return 0;
		}
	}
}

U281358 学长的因子 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/U281358这个题目就是一个求因子的题目 但是有一点就是 题目里的x和y的范围都是10^5 

他让我们求x*y的因子 相乘为10^10 很显然就是会超时 

那我们要知道一点 x*y的因子就是x和y的因子相乘 这样我么只需要单独算出x和y的因子 再把他们的因子相乘即可  如何避免重复?运用set 自动删除重复内容

具体代码:

 

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<set>
using namespace std;

int main() {
    long long x, y;
    cin >> x >> y;
    set<int>num1, num2,num3;
	for (int i = 1; i * i <= x; i++) {
		if (x % i == 0) {
			num1.insert(i);
			num1.insert(x/ i);
		}
	}
	for (int i = 1; i * i <= y; i++) {
		if (y % i == 0) {
			num2.insert(i);
			num2.insert(y / i);
		}
	}
	for (auto i : num1)for (auto j : num2) {
		num3.insert(i * j);
	}
    cout << num3.size();
    return 0;
}

U271276 小施的不等式 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/U271276这个题目是一个经典的并查集的题目

判断等式是否有错误

如果相等 就相当于这两个是亲戚  如果是亲戚之后来了一个不相等 那么输出NO

但是 这个题目有个细节 

当我们先来等号再来不等号 我们判断是很容易 直接输出NO

但是如果我们先来不等号再来等号 就比较麻烦 因为我们还没有通过等号建立亲戚关系 当我们一开始出现不等号的时候 如何避免后面出现的等号时  我们输出NO呢?

我们可以在先出现不等号的时候 构建一个小小下标 rank1[a] = b 这个是用来干啥?

标记 我们的a和b是不相等的 如果在之后出现相等的情况 直接输出NO

这样我们就可以避免先出现不等号再出现等号的尴尬了

具体代码为:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
const int N = 5 * 1e5 + 5;
int pre[N];
int rank1[N];
int find(int x) {
	if (pre[x] == x)return x;
	return pre[x] = find(pre[x]);
}
void join(int x, int y) {
	int fx = find(x);
	int fy = find(y);
	if (fx != fy) {
		pre[fx] = fy;
	}
}
int main() {
	int n, q;
	cin >> n >> q;
	for (int i = 1; i <= n; i++) {
		pre[i] = i;
	}
	int flag = 0;
	for (int i = 1; i <= q; i++) {
		int a, b;
		cin >> a >> b;
		int c;
		cin >> c;
		if (c == 1) {
			if (rank1[a] != b) {
				join(a, b);
			}
			else {
				cout << "NO";
				return 0;
			}
		}
		else {
			if (find(a) == find(b)) {
				cout << "NO";
				return 0;
			}
			rank1[a] = b;
		}
	}
	cout << "YES";
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值