爪哇部落 新生选拔赛 2020
1.A sort problem
2.Travel
3.小爪喜欢的那个女孩
4.小爪的数学游戏
Description
小爪常常因为数学太菜而无法做题,又在学数学了。这次是以游戏的形式。在游戏的开始,小爪会得到一个数N(0<=N<=1,000,000)。此时小爪的分数为0。如果N是奇数,那么小爪就会把它乘以3后再加1。如果N是偶数,那么这个数就会被除以2。数字每变动一次,小爪就得到1分。当N的值等于1时,游戏结束,此时的分数就是小爪在这局游戏中的最终得分。
以下是N=5时,一局游戏的完整过程:
N 操作后所得数 注释 总分
5 16 3*5+1 1
16 8 16/2 2
8 4 8/2 3
4 2 4/2 4
2 1 2/2 5
Input
第1行: 一个整数,N
Output
第1行: 输出一个整数N,即小爪在这局游戏中的最终得分;若不能计算出得分,则输出"INF"(不带引号)表示小爪获得了无穷大的分数。
Sample Input 1
112
Sample Output 1
20
3n + 1 的问题,这题有个坑,就是输入的要求是一个整数,而不是一个正整数,所以,要特判n == 0的时候
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int read()
{
int w = 1, s = 0;
char ch = getchar();
while (ch < '0' || ch>'9') { if (ch == '-') w = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
return s * w;
}
//------------------------ 以上是我常用模板与刷题几乎无关 ------------------------//
int main()
{
int n,cnt;
cnt = 0;
scanf("%d",&n);
//
if (n == 0) {
printf("INF\n");
return 0;
}
while (n != 1) {
if (n % 2 == 0) {
n = n / 2;
cnt++;
}
else if (n % 2 != 0) {
n = n * 3 + 1;
cnt++;
}
}
printf("%d\n", cnt);
return 0;
}
5.小爪的数字识别算法
Description
小爪发现数字识别算法有一个基础的坎它跨不过去了。 已知数字已被实现识别为只包含 * 和 . 的5行字符串了,你能帮帮它输出它的值是多少吗?
0-9分别被识别如下:
.***.
.*.*.
.*.*.
.*.*.
.***.
.**..
..*..
..*..
..*..
.***.
.***.
...*.
.***.
.*...
.***.
.***.
...*.
.***.
...*.
.***.
.*.*.
.*.*.
.***.
...*.
...*.
.***.
.*...
.***.
...*.
.***.
.***.
.*...
.***.
.*.*.
.***.
.***.
...*.
...*.
...*.
...*.
.***.
.*.*.
.***.
.*.*.
.***.
.***.
.*.*.
.***.
...*.
.***.
Input
5行由 ‘*’ 和 ‘.’ 组合的字符串(每行字符串的长度不会超过50000)
Output
一行:表示输入的值,用阿拉伯数字表示。
Sample Input 1
.**..
..*..
..*..
..*..
.***.
Sample Output 1
1
Sample Input 2
.***..***..*.*.
.*......*..*.*.
.***..***..***.
...*....*....*.
.***..***....*.
Sample Output 2
534
考察对字符串的运用,详情看代码,挺简单的。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int read()
{
int w = 1, s = 0;
char ch = getchar();
while (ch < '0' || ch>'9') { if (ch == '-') w = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
return s * w;
}
//------------------------ 以上是我常用模板与刷题几乎无关 ------------------------//
const int N = 50010;
char a[N];
char b[N];
char c[N];
char d[N];
char e[N];
int main()
{
scanf("%s",a);
scanf("%s",b);
scanf("%s",c);
scanf("%s",d);
scanf("%s",e);
int len = strlen(a) / 5;
int m = -5;
for(int i = 0;i < len; i++) {
m += 5;
if(a[m+1]=='*'&&a[m+2]=='*'&&a[m+3]=='.') {
printf("1");
continue;
}
else if(a[m+1]=='*'&&a[m+2]=='.'&&a[m+3]=='*') {
printf("4");
continue;
}
else if(c[m+1]=='*'&&c[m+2]=='.'&&c[m+3]=='*') {
printf("0");
continue;
}
else if(d[m+3]=='.') {
printf("2");
continue;
}
else if(c[m+1]=='.') {
printf("7");
continue;
}
else if(b[m+1]=='.') {
printf("3");
continue;
}
else if(b[m+3]=='.'&&d[m+1]=='.') {
printf("5");
continue;
}
else if(b[m+3]=='.') {
printf("6");
continue;
}
else if(d[m+1]=='.') {
printf("9");
continue;
} else {
printf("8");
continue;
}
}
cout << endl;
return 0;
}
6.小爪的长皮带
7.小爪博弈
Description
有一天,小爪跟一只猪杠上了,奈何那只猪就算当年和大猪抢饲料的小智猪。这下小爪的噩梦来了,因为它并不会博弈。它们还是比赛拿石头,有一排石头,每一堆有若干个石头,他们每一次都要轮流从一堆石头上拿一个或多个石头,拿走最后一个的获胜。
小猪认为自己有必胜的把握能够赢小爪,它让小爪先拿,你觉得小猪有胜利的可能性吗?
Input
第一行 T ,表示有T个测试用例 ( 0 < T < 1000 ) (0<T<1000) (0<T<1000)
每个用例有2行:
第一行为N,表示石头的堆数。 ( 0 < n < 1000 ) (0<n<1000) (0<n<1000)
第二行为N个正整数,表示每一堆石头的个数。
Output
如果小猪有胜利的可能输出YES,否则输出NO
Sample Input 1
1
1
1
Sample Output 1
NO
Sample Input 2
1
5
1 1 1 1 1
Sample Output 2
NO
注意这题不是博弈论!!!!(小爪不会博弈) 输出YES的条件是:小猪有胜利的可能 输出NO的条件是:小猪没有胜利的可能
如果全是1,那么就奇数堆的赢,偶数堆输,假设有一个数不是1,那么就可能可以实现反转,则小猪有赢的可能性。
所以思路是:
小猪一定输的情况只有1种: 堆数为奇数,且每堆都是1颗石头 其他情况小猪都有赢得可能性。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int read()
{
int w = 1, s = 0;
char ch = getchar();
while (ch < '0' || ch>'9') { if (ch == '-') w = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
return s * w;
}
//------------------------ 以上是我常用模板与刷题几乎无关 ------------------------//
const int N = 1010;
int a[N];
int main()
{
int t = read();
while(t--) {
int n = read();
int one = 0, cnt = 0;
for(int i = 0;i < n;i++) {
a[i] = read();
if(a[i] == 1)
one++;
else
cnt++;
}
if(one % 2 == 1 && cnt == 0)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}
8.javatribe
9.小爪的几何
10.小爪的珠宝选择(线段树简单题)
Description
小爪发现了 N 个珠宝,他用超能力识别出了这 N 个珠宝的价值,但是他发现他只能带走 [ L, R]
区间的珠宝,由于使用了超能力,副作用就是选择区间的珠宝价值的最小值和最大值的差值不能超过 m, 小爪想知道他最多能得到多少珠宝的价值?
Input
第一行两个整数,N 和 M。 ( 1 <= N,M <= 1e6)
第二行 N 个整数,表示珠宝的价值。 ( 1 <= a[i] <= 1e9)
Output
一个数字,小爪能得到的最多财富。
Sample Input 1
6 2
2 1 2 1 5 3
Sample Output 1
8
理解 线段树的区间查询 即可 (并且代码有详细解释)
关于 线段树的区间查询 ,可以查看这篇文章(内有模板题 HDU - 1166 敌兵布阵 及图文详解):
线段树相关知识点及模板题:https://blog.csdn.net/m0_46272108/article/details/108955623
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
//#define int ll
#define inf 0x3f3f3f3f
using namespace std;
int read()
{
int w = 1, s = 0;
char ch = getchar();
while (ch < '0' || ch>'9') { if (ch == '-') w = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
return s * w;
}
//最大公约数
int gcd (int x,int y) {
if(x<y) swap(x,y);//很多人会遗忘,大数在前小数在后
//递归终止条件千万不要漏了,辗转相除法
return x % y ? gcd(y, x % y) : y;
}
//计算x和y的最小公倍数
int lcm (int x,int y) {
return x * y / gcd(x, y);//使用公式
}
//------------------------ 以上是我常用模板与刷题几乎无关 ------------------------//
const int N = 1000010;
struct node
{
int l, r;
int maxx, minn;
}tr[N << 2];
int a[N];
ll sum[N];
int n, k;
void pushup(int cur)
{
tr[cur].maxx = max(tr[cur << 1].maxx, tr[cur << 1 | 1].maxx);
tr[cur].minn = min(tr[cur << 1].minn, tr[cur << 1 | 1].minn);
}
void build(int cur, int l, int r)
{
tr[cur].l = l, tr[cur].r = r;
if (l == r) {
tr[cur].maxx = tr[cur].minn = a[l];
return;
}
int mid = l + r >> 1;
build(cur << 1, l, mid);
build(cur << 1 | 1, mid + 1, r);
pushup(cur);
}
int query_maxx(int cur, int l, int r)
{
if (l == tr[cur].l && r == tr[cur].r)
return tr[cur].maxx;
int mid = tr[cur].l + tr[cur].r >> 1;
int ans = -inf;
if (r <= mid)
return max(ans, query_maxx(cur << 1, l, r));
else if (l > mid)
return max(ans, query_maxx(cur << 1 | 1, l, r));
else {
ans = max(ans, query_maxx(cur << 1, l, mid));
ans = max(ans, query_maxx(cur << 1 | 1, mid + 1, r));
return ans;
}
}
int query_minn(int cur,int l,int r) {
if (l == tr[cur].l && r == tr[cur].r)
return tr[cur].minn;
int mid = tr[cur].l + tr[cur].r >> 1;
int ans = inf;
if(r <= mid)
return min(ans, query_minn(cur << 1, l, r));
else if(l > mid)
return min(ans, query_minn(cur << 1 | 1, l, r));
else {
ans = min(ans, query_minn(cur << 1, l, mid));
ans = min(ans, query_minn(cur << 1 | 1, mid + 1, r));
return ans;
}
}
int main()
{
while(~scanf("%d %d",&n,&k)) {
for(int i = 1; i <= n; i++) {
a[i] = read();
sum[i] = sum[i - 1] + a[i];
}
build(1, 1, n);
ll ans = 0;
for (int i = 1; i <= n; i++) {
int l = 1, r = n;
while (l <= r) {
int mid = l + r >> 1;
ll maxnum = query_maxx(1, i, min(i + mid, n));
ll minnum = query_minn(1, i, min(i + mid, n));
if(maxnum - minnum <= k) l = mid + 1;
else r = mid - 1;
}
ans = max(ans, sum[min(i + l - 1, n)] - sum[i - 1]);
}
printf("%lld\n", ans);
}
return 0;
}
11.小爪的数学猜想
Description
小爪有一个 N 个元素的 a数组,且小爪设定 Sum 为前缀和,即 Sum-i 是数组的第一个元素到第 i 个元素求和之后的数,mod
为取余。小爪猜想,是否有 (Sum-j) - (Sum-i) == 0 mod m 。 (1 <= i < j <= N)
Input
第一行两个整数,分别为 N,M。 (1 <= N <= 1e6, 1 <= M <= 1e9) 第二行N个整数 ,分别为小爪的 a 数组的元素。 (1 <= ai <= 1e9)
Output
如果是就输出yes,否则就输出no。
Sample Input 1
5 4
1 2 3 4 5
Sample Output 1
yes
考察STL(map)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<unordered_map>
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int read()
{
int w = 1, s = 0;
char ch = getchar();
while (ch < '0' || ch>'9') { if (ch == '-') w = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
return s * w;
}
//------------------------ 以上是我常用模板与刷题几乎无关 ------------------------//
const int N = 1000010;
char a[N];
int sum[N];
unordered_map<int,int>vis;
int main()
{
int n = read(), m = read();
for (int i = 1; i <= n; i++) {
int x = read();
sum[i] = sum[i - 1] + x;
int tmp = sum[i] % m;
vis[tmp]++;
}
if (vis[0] >= 1) {
printf("yes\n");
} else {
int flag = 0;
for(auto i:vis) {
if(i.second >= 2) {
flag = 1;
break;
}
}
if(flag)
printf("yes\n");
else
printf("no\n");
}
return 0;
}
12.小爪的签到题
略