U280826 学长的数(1) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://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)https://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)https://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)https://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;
}