河南萌新联赛2024第(四)场:河南理工大学

【牛客】河南萌新联赛2024第(四)场:河南理工大学

不按顺序写:

D:

题目大意:给n个数字,判断是不是素数

思路:注意262144K=256MB N=1e8跑一个欧拉筛 然后不用二分,新建一个is__prime数组记录就好了 O(1)的判断

#include<iostream>
#include <cstdio>
#define lld long long
const int N =1e8+9;
bool is_prime[N],is__prime[N];
int prime[N],n,cnt;
using namespace std;
void Euler(int x){
for(int i=2;i<=x;++i){
if( !is_prime[i] ) prime[++cnt]=i,is__prime[i]=1;
for(int j=1 ; j<=cnt && i*prime[j]<=x ; ++j){
is_prime[ i * prime[j] ]=true;
if( i % prime[j]== 0) break;
}
}
}
bool check(int x){
int L=1,R=cnt;
while(L <= R){
int mid = L + (R-L)/2;
if(prime[mid] == x) return true;
else if(prime[mid] < x)
L = mid+1;
else
R = mid-1;
}
return false;
}
int main()
{
int n;
cin>>n;
Euler(N);
for(int i=1;i<=n;++i){
int x;
cin>>x;
if(is__prime[x]) cout<<"Yes";
else cout<<"No";
cout<<"\n";
}
return 0;
}

E

大意:给一个区间[L,R] 回答两个问题 1.有多少素数 2.多少个子区间&起来的的值为0

思路:先跑个1e8的线性筛 问题一:lower_bound跑第一个​大于等于L的下标L__ ,upper_bound跑第一个大于R的下标R__,这样就免去了+1 比如[2,3,5,7,11,13] 让你求[4,14]和[4,13]会发现跑upper_bound不用判断右端点是不是素数,答案就是 R__-L__

问题二:

/*
2之外的所有素数都是奇数,也就是说都是以1结尾的二进制
所以必须有2
接上文,如果primes[L__]不是2 输出0
简单枚举一下:
0000010 : 2
0000011 : 3
0000101 : 5
0000111 : 7
0001011 : 11
发现 2&3=2 不行
特判一下 如果只有两个素数 或者没有2 输出0
2&3&5=0
2&5&7=0
所以第一问的长度减去2就好了
*/
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define lld long long
const int N = 1e8 + 9;
bool is_prime[N];
int primes[N];
int cnt=0;
void Euler(int x) {
for (int i = 2; i <= x; ++i) {
if (!is_prime[i]) {
primes[++cnt]=i;
}
for (int j = 1; j <=cnt && i * primes[j] <= x; ++j) {
is_prime[i * primes[j]] = true;
if (i % primes[j] == 0) break;
}
}
}
void solve() {
int L, R;
cin >> L >> R;
vector<int> prime__;
int l__ = lower_bound(primes+1, primes+1+cnt, L)-primes;
int r__ = upper_bound(primes+1, primes+1+cnt, R)-primes;
int ans = r__ - l__;
cout << ans << " ";
if(l__!=1 or ans<=2) cout<<"0";
else{
cout<<ans-2;
}
cout<<"\n";
}
int main() {
int T;
cin >> T;
Euler(N);
while (T--) {
solve();
}
return 0;
}

F:

大意:给一个字符表达式形如 111+999999+22 求值 和按照数字从大到小排列字符

思路:跑一遍字符 没遇到加号就把数字存到x中,然后计算x的值,接着存到一个数组num里,"+"的数量比数字少 单独在计算一次 最后sort数组num就行

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <algorithm>
#define lld long long
#define ios std::ios::sync_with_stdio(false);std::cin.tie(0);
using namespace std;
void turn(string& x, lld& result, vector<lld>& num) {
lld R = 0;
int len = x.size();
for(int i = 0; i < len; ++i) {
R = R * 10 + (x[i] - '0');
}
result += R;
num.push_back(R);
}
bool cmp(int a,int b){
return a>b;
}
void solve() {
string s, x;
lld result = 0;
vector<lld> num;
cin >> s;
for(int i = 0; i < s.size(); ++i) {
if(s[i] != '+') {
x.push_back(s[i]);
}
if(s[i] == '+') {
turn(x, result, num);
x.clear();
}
}
//加号后面还有数字没处理
turn(x, result, num);
sort(num.begin(), num.end(),cmp);
int len_ = num.size()-2;
for(int i = 0; i <= len_; ++i) {
cout << num[i];
cout<<"+";
}
//最后一个数字单独输出
cout<<num[len_+1];
cout << "\n" << result << "\n";
}
int main() {
ios;
int T = 1;
while(T--) {
solve();
}
return 0;
}

H:

大意:一个傻逼贪心题目 x个金币 n个人 你作为一号 每个人都想获得更多的金币,你可以随意选取金币 选完后所有人投票,一半人投票通过你才能获得金币,求你能获得的最多金币

思路:尤其傻逼的题目 你只需要给一半的人分配1个金币就可以获得他们的投票,然后判断奇数偶数就好了 举例 x=100 n=5 分配成[98,1,1,0,0]就行 x=100,n=6 分配成[98,1,1,0,0,0] 保证过一办就行

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--) {
int x, n;
cin >> x >> n;
// 计算通过提案所需的最少票数
int len=0;
if(n%2==0)
len = n/2;
else
len = (n / 2) + 1;
// 计算需要给出的金币数量
int coions = len - 1; // 给每个需要投票支持的恶魔发1个金币
// 剩下的金币都归你自己
int ans = x - coions;
cout << ans << "\n";
}
return 0;
}

J:

大意:给出一棵有根树,根是root 每个节点可以到达自己的任意子节点 对于Fib数列定义为 F1=1,F2=2,Fi=Fi−1+Fi−2 给出Q个询问 每次两个数 x,k 生成一个集合{x+Fi,i>=k x+Fi <=n} 的一些点 求一个节点U 能到达集合中的所有点且U距离根root最远

(1)Fix,kS(2)v,uLCA(u,v)(3)S,Fi30(4)S00(5)LCATarjan

#include <iostream>
#include <vector>
#include <cmath>
#include <cstring>
using namespace std;
#define ios std::ios::sync_with_stdio(false); std::cin.tie(0);
const int N = 1e5 + 9;
int n, Q, root;
int logn;
vector<vector<int>> anc;
vector<int> depth;
vector<int> head;
vector<struct node> e;
struct node {
int to, val, next;
};
void add(int u, int v, int val) {
static int idx = 0;
e[idx] = {v, val, head[u]};
head[u] = idx++;
}
void bd() {
cin >> n >> root >> Q;
logn = log2(n);
head.assign(n + 1, -1);
e.resize(2 * (n - 1)); // Adjust size based on the number of edges
anc.assign(n + 1, vector<int>(logn + 1, -1));
depth.assign(n + 1, 0);
for (int i = 1; i <= n - 1; ++i) {
int u, v;
cin >> u >> v;
add(u, v, 0);
add(v, u, 0);
}
}
void dfs(int u, int fa) {
anc[u][0] = fa;
for (int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].to;
if (v == fa) continue;
depth[v] = depth[u] + 1;
dfs(v, u);
}
}
void init() {
for (int j = 1; j <= logn; ++j) {
for (int i = 1; i <= n; ++i) {
int v = anc[i][j - 1];
if (v != -1) {
anc[i][j] = anc[v][j - 1];
}
}
}
}
int LCA(int u, int v) {
if (depth[v] > depth[u])
swap(u, v);
for (int i = logn; i >= 0; --i) {
if (depth[u] - (1 << i) >= depth[v]) {
u = anc[u][i];
}
}
if (u == v) return u;
for (int i = logn; i >= 0; --i) {
if (anc[u][i] != anc[v][i]) {
u = anc[u][i];
v = anc[v][i];
}
}
return anc[u][0];
}
vector<int> F(N);
void f() {
F[1] = 1;
F[2] = 2;
int x = 2;
while (1) {
F[x + 1] = F[x] + F[x - 1];
x++;
if (F[x] > n) break;
}
}
void solve(int u, int v) {
if(v>30){
cout<<"0"<<"\n";
return ;
}
vector<int> S;
int pos = v;
while (u + F[pos] <= n) {
S.push_back(u + F[pos]);
pos++;
if (u + F[pos] > n) break;
}
if (S.empty()) {
cout << "0";
} else {
if (S.size() == 1) {
cout << S[0];
} else {
int ans = LCA(S[0], S[1]);
for (size_t k = 2; k < S.size(); ++k) {
ans = LCA(ans, S[k]);
}
cout << ans;
}
}
cout << "\n";
}
int main() {
ios;
bd();
f();
dfs(root, -1);
init();
for (int i = 1; i <= Q; ++i) {
int u, v;
cin >> u >> v;
solve(u, v);
}
return 0;
}
posted @   phrink  阅读(57)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示