2021/1/23黑龙江农垦科技职业学院喜迎寒假多校联赛2(快乐ak场)题解

传送门:黑龙江农垦科技职业学院喜迎寒假多校联赛2(快乐ak场)

白天去老姐家撸狗勾了,没打,回家补的

进入比赛先看了眼榜,发现A题A的人最少,那我偏偏就从A题顺着往下做嘿嘿嘿(然后piapia打脸)

A 数组截取

注意!!本题只得了90!!原因是超时,并没有AC!!

有一段数组n 从中截取和为k的一部分 最长可以截取多长?(如果截取不到正好为k的情况下输出-1)
注意:
出题人:出个数组截取吧;验题人:数据太弱了加强一下;出题人:陷入沉思,OK
本题因为验题人吐槽,数据太弱所以加强了一点点,一点点.......
因为数据比较多 请使用你认为最快的读取方式 最省内存的运算方法。反正C++标程 500ms 256mb 内跑过去了。
输入描述:
第一行输入两个整数 n,k
1<n<=2×107
0<=k<=1018
第二行输入n个正整数(包含0)
a1 a2 .....an (0<=ai<=1012) 1<=i<=n
输出描述:
输出运算结果

输入
10 3
3 3 1 1 1 0 0 0 3 3

输出
6

拿到题,没什么特殊的思路,就是从头开始加,大了就减掉最前面的,然后记录长度更新最大值就好了

一开始用了个队列储存,后来想了想发现没有必要,就改成了一个head指向数列里的第一个数,然而最后还是没AC

快速读入快速输出都用了,还用了inline玄学加速,最后还手动O2都没用,做了半个小时,草,毁灭吧不做了

贴上90分代码,指不定哪天良心发现就想开了

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#pragma GCC optimize(2)
#define ll long long
using namespace std;

const int maxn = 2e7 + 1;
ll n, k, a[maxn], sum, cnt = 1, ans = -1;

inline ll read() {
  ll x = 0, k = 1;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar()) if (ch == '-') k = -1;
  for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
  return x * k;
}

inline void printt(ll x) { 
  if (x < 0) { 
    putchar('-'); 
    x = -x; 
  } 
  if(x > 9) printt(x / 10); 
  putchar(x % 10 + '0'); 
} 

int main() {
  n = read(); k = read();
  for (int i = 1; i <= n; i++) a[i] = read();
  for (int i = 1; i <= n; i++) {
  	sum += a[i];
    while (sum > k) {
      sum -= a[cnt];
      cnt++;
    }
    if (sum == k) 
      ans = max(ans, i - cnt + 1);
  }
  printt(ans);
  return 0;
}

B 群友们在排列数字

题目描述
群友们在玩一个游戏,共n个人在玩 每个人要在0-(n-1)中选一个数,注意每个数只能选择一次,
然后按照先后选择顺序拼成一个数,计算组成的数字是否可以整除k,
群友们想知道,如果选择方案不重复,最多有多少种情况可以整除k?
如果不可能整除k请输出-1;
输入描述:
第一行输入两个正整数 n,k
1<=n<=10,1<=k<=107
输出描述:
输出结果

输入
2 1

输出
2

一个dfs,直接暴力每一种情况看看能不能整除就可以

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#define ll long long 
using namespace std;

const int maxn = 11;
ll n, k, ans, vis[maxn];

inline ll read() {
  ll x = 0, f = 1;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
  return x * f;
}

inline void printt(ll x) { 
  if (x < 0) {
    putchar('-'); 
    x = -x; 
  }
  if(x > 9) printt(x / 10); 
  putchar(x % 10 + '0'); 
} 

inline void dfs(ll num, ll now) {
  if (num == n) {
    if (now % k == 0) ans++;
    return;
  }
  for (int i = 0; i < n; i++) {
    if (vis[i] == 0) {
      vis[i] = 1;
      dfs(num + 1, now * 10 + i);
      vis[i] = 0;
    }
  }
}

int main() {
  n = read(); k = read();
  dfs(0, 0);
  if (ans == 0) printf("-1");
  else printt(ans);
  return 0;
}

C gg查成绩

题目描述
这一天gg拿到了一份,超多的考试数据a 。
老师要求他按照询问数据告诉老师,第几个到第几个同学的分数和是多少 ?
gg最近入职字节跳动了,没有时间处理这种极其简单的问题,所以请你顺手秒一下。
输入描述:
第一行n m ( n个同学 m次询问)
1<=n<=106
1<=m<=104
第二行输入n个整数表示成绩
a1 a2 .....an (0<=ai<=100) 1<=i<=n
以下m行为两个整数bi bj 表示第几个到第几个同学(从1开始)
1<=bi<=bj<=n
输出描述:
m行查询结果

输入
10 3
11 22 33 44 55 66 77 88 99 10
1 4
2 10
5 7

输出
110
494
198

读完题:啊哈!线段树~(dbq最近在做线段树的题,看见查询区间和条件反射想到线段树...)

交完评分提交tag的时候才发现用前缀和就能做...下面放上我的线段树...真是小题大做了啊

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#define ll long long 
using namespace std;

const int maxn = 4e6 + 10;
ll n, m, a[maxn], x, y, ans;
struct node {
  ll l, r, sum;
}tree[maxn]; 

inline void build(ll i, ll l, ll r) {
  tree[i].l = l; tree[i].r = r;
  if (l == r) {
  	tree[i].sum = a[l];
  	return;
  }
  ll mid = (l + r) >> 1;
  build(i * 2, l, mid);
  build(i * 2 + 1, mid + 1, r);
  tree[i].sum = tree[i * 2].sum + tree[i * 2 + 1].sum;
}

inline ll search(ll i, ll l, ll r){
    if (tree[i].l >= l && tree[i].r <= r)
        return tree[i].sum;
    if (tree[i].r < l || tree[i].l > r) return 0;
    ll sum=0;
    if (tree[i * 2].r >= l) sum += search(i * 2, l, r);
    if (tree[i * 2 + 1].l <= r) sum += search(i * 2 + 1, l, r);
    return sum;
}

inline ll read() {
  ll x = 0, f = 1;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
  return x * f;
}

int main() {
  n = read(); m = read();
  for (int i = 1; i <= n; i++) a[i] = read();
  build(1, 1, n);
  for (int i = 1; i <= m; i++) {
    x = read(); y = read();
    ans = search(1, x, y);
    printf("%lld\n", ans);
  }
  return 0;
}

D issue与lifehappy给学生分组

题目描述
issue与lifehappy在给学生分组 现在他们手里有一组n分学生量化好的数据a 这份数据是一个数字,代表学生的大致实力
他们要给学生分成m组并且要求总实力和的最大值最小(ccpc抢名额战略,分散一点)
不过学生们已经拉帮结派的排好队了 所以 issue与lifehappy只能选取这组数据中的连续队列。
输入描述:
第一行 n m n个学生 分成m组
1<=m<=n<=106
第二行为n正整数an
a1 a2 .....an (0<=ai<=1011) 1<=i<=n(保证最终结果在ull内)
输出描述:
输出分组后总实力最大值的最小

输入
5 3
1 8 9 4 2

输出
9

二分答案,枚举可能的数值然后判断

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#define ll long long 
#define ull unsigned long long
using namespace std;

const int maxn = 1e6 + 10;
ll n, m, a[maxn];
ull l, r, mid;

inline ll read() {
  ll x = 0, f = 1;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
  return x * f;
}

inline bool work(ull x) {
  ull sum = 0;
  ll cnt = 1;
  for (int i = 1; i <= n; i++) {
  	sum += a[i];
  	if (sum > x) {
  	  sum = a[i];
  	  cnt++;
  	}
  	if (cnt > m) return false;
  }
  return true;
}

int main() {
  n = read(); m = read();
  for (int i = 1; i <= n; i++) {
  	a[i] = read();
    r += a[i];
    l = l > a[i] ? l : a[i];
  }
  while (l < r) {
  	mid = (l + r) >> 1;
  	if (work(mid)) r = mid;
  	else l = mid + 1;
  }
  cout << l << endl;
  return 0;
}

E 删删删越小越好

题目描述
这一天Kadia与Majiagou在教学弟,
突然提出了一个问题 给你一个超大的数字 让你从中删掉几位 怎么让他最小?
这种签到题不会还有人写不出来吧 不会吧不会吧
输入描述:
第一行输入一个整数N
1<=len(N)<=2×107
第二行输入一个整数k代表删除几个数字
0<=k<=len(N)
输出描述:
输出结果

输入
10000
1

输出
0

说明
删掉1结果为0

输入
12347897187194164979
10

输出
1114164979

之前讲过这种题,我当时傻乎乎地先删大的数,于是就听取WA声一片

这题的正解是从前往后删,保留最小的数,然后比它大的就全删掉,直到不能删了为止

例如:1234441119111中删8个就会删掉23444、9然后再删1

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#define ll long long 
using namespace std;

const int maxn = 2e7 + 1;
int k, head;
char a[maxn];

inline ll read() {
  ll x = 0, f = 1;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
  return x * f;
}

int main() {
  scanf("%s", a + 1); k = read();
  int len = strlen(a + 1);
  for (int i = 1; i <= len; i++) {
    while (k > 0 && head >= 1 && a[head] > a[i]) {
      head--;
      k--;
    }
    a[++head] = a[i];
  }
  int now = 1;
  while (a[now] == '0' && now < head) now++;
  while (k > 0) {
  	head--;
  	k--;
  }
  for (int i = now; i <= head; i++) printf("%c", a[i]);
  return 0;
}

F happy的异或运算

题目描述
我们都知道有一种位运算叫做异或,那么这道题是一道思维题。
给出一个整数n,请求出1-n之间选取两个数进行异或最大能得出多大?(两个数可以相同)
输入描述:
1 ≤ N ≤1018
输出描述:

输入
10000
输出
16383

输入
648
输出
1023

输入
324
输出
511

这是一道...结论题,只需让n对应的二进制的每一位都是1,就可以得到答案

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <queue>
#define ll long long
using namespace std;

ll n, ans;

inline ll read() {
  ll x = 0, f = 1;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
  return x * f;
}

int main() {
  n = read();
  while (n) {
  	ans = ans << 1 | 1;
  	n >>= 1;
  }
  printf("%lld\n", ans);
  return 0;
}

G Alan%%%

题目描述
又是欢快的一天,牛客多校算法训练营4又在日常%Alan。qcjj想知道到底Alan被%了多少次,所以整理了一下聊天记录。
如果一句话中存在Alan,那么那句话中的%都算%了Alan。由于可能话中有空格,所以去掉空格后形成的Alan也算Alan。
输入描述:
第一行输入整数n表示聊天记录行数
1<=n<=1000
以下n行每行一个字符串s代表聊天记录
1<=s.length<=1000
输出描述:
输出%Alan次数

输入
5
%alan%%
%Alan%%%
cdqwsq%% A l a n%%
%AC lan%%
%Alan%%%

输出
12

简单的模拟,没什么好说的

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <set>
#include <map>
#include <algorithm>
#include <queue>
#include <vector>
#define ll long long
using namespace std;

int n, ans;
string s;

inline ll read() {
  ll x = 0, f = 1;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
  return x * f;
}

int main() {
  n = read();
  for (int i = 1; i <= n; i++) {
    getline(cin, s);
    int cnt = 0, flag = 0;
    int len = s.size();
    for (int i = 0; i < len; i++) {
      if (s[i] == '%') cnt++;
      if (s[i] == ' ') continue;
      if (s[i] == 'A') flag = 1;
      else if (flag == 1) {
      	if (s[i] == 'l') flag = 2;
      	else {
      	  flag = 0;
      	  break;
      	}
      }
      else if (flag == 2) {
      	if (s[i] == 'a') flag = 3;
      	else {
      	  flag = 0;
      	  break;
      	}
      }
      else if (flag == 3) {
      	if (s[i] == 'n') flag = 4;
      	else {
      	  flag = 0;
      	  break;
      	}
      }
    }
    if (flag == 4) ans += cnt;
  }
  printf("%d\n", ans);
  return 0;
}

H cg写项目

题目描述
这一天cg写了一个卡迪亚酒店客户端,客户端的数据是一张由用户名s,密码m,性别x,电话h组成的表,他想以用户的用户名为基准进行一下排序,短的在前,同样长度按照字典序小的在前,同用户名先输入的在前面。但是曹哥太忙了所以找你帮忙写一下数据处理。
输入描述:
n分数据
1<=n<=100
以下n行 为 s m x h
1<= s.length <=20
1<= m.length <=20
1<= x.length <=20
1<= h.length <=20
输出描述:
根据用户名排序规则排序后输出

输入
5
td1336065617 1336065617 n 13766949653
1336065617 1336065617 nc 137
ad1336065617 1336065617 na 111
03360651778 1 9 8
1 1 1 1

输出
1 1 1 1
1336065617 1336065617 nc 137
03360651778 1 9 8
ad1336065617 1336065617 na 111
td1336065617 1336065617 n 13766949653

用结构体sort一下就过了,唯一需要注意的就是排序方式,一开始看错了wa了一发QwQ

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <queue>
#define ll long long 
using namespace std;

int n;
struct node{
  string name, pasw, sex, tel, len, num;
}a[110];

inline ll read() {
  ll x = 0, f = 1;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
  return x * f;
}

inline bool cmp(node x, node y) {
  if (x.len != y.len) return x.len < y.len;
  else if (x.name != y.name) return x.name < y.name;
  return x.num < y.num;
}

int main() {
  n = read();
  for (int i = 1; i <= n; i++) {
  	cin >> a[i].name >> a[i].pasw >> a[i].sex >> a[i].tel;
  	a[i].len = a[i].name.size();
    a[i].num = i;
  }
  sort(a + 1, a + 1 + n, cmp);
  for (int i = 1; i <= n; i++) 
    cout << a[i].name << " " << a[i].pasw << " " << a[i].sex << " " << a[i].tel << endl;
  return 0;
}

I cg写项目加强版

和上题一样的,改一下大小就可以了

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <queue>
#define ll long long 
using namespace std;

int n;
struct node{
  string name, pasw, sex, tel, len;
  int num;
}a[1000010];

inline ll read() {
  ll x = 0, f = 1;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
  return x * f;
}

inline bool cmp(node x, node y) {
  if (x.len != y.len) return x.len < y.len;
  else if (x.name != y.name) return x.name < y.name;
  return x.num < y.num;
}

int main() {
  n = read();
  for (int i = 1; i <= n; i++) {
  	cin >> a[i].name >> a[i].pasw >> a[i].sex >> a[i].tel;
  	a[i].len = a[i].name.size();
    a[i].num = i;
  }
  sort(a + 1, a + 1 + n, cmp);
  for (int i = 1; i <= n; i++) 
    cout << a[i].name << " " << a[i].pasw << " " << a[i].sex << " " << a[i].tel << endl;
  return 0;
}

J 比赛开始了清楚姐姐喊了一句:签到了签到了

题目描述
比赛开始了清楚姐姐喊了一句:签到了签到了 选手们纷纷开始签到,现在给出n个数字代表选手们签到所用秒数 请给出第几个选手最先签到。同秒数先输入的算快。
(不会吧 不会吧 不会有人用牛客不知道清楚姐姐吧)
输入描述:
第一行输入一个整数n
1<=n<=10000
第二行输入n个整数s
0<=s<=1000
输出描述:
一个数

输入
5
5 3 2 4 1

输出
5

签到题

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <queue>
#define ll long long 
#define INF 0x7fffffff
#pragma GCC optimize(2)
using namespace std;

int x, y = INF, n, ans;

int main() {
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> x; 
    if (x < y) {
      y = x;
      ans = i;
    }
  }
  printf("%d", ans);
  return 0;
}

完结撒花~

不早了,洗洗睡了

posted @ 2021-01-24 00:16  Moominn  阅读(227)  评论(0编辑  收藏  举报