牛客ioi周赛20——普及组
完全数
题意: 判断一个数的不包括其本身的约数和与其本身的大小关系。
数据范围:
题解: 枚举到暴力求解即可。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
int main()
{
scanf("%lld", &n);
ll res = 0;
int last = sqrt(n + 0.5);
for(int i = 1; i <= last; ++i) {
if(n % i == 0) {
res += i;
if(1ll * i * i != n) res += n / i;
}
}
res -= n;
if(res == n) puts("Pure");
else if(res < n) puts("Early");
else puts("Late");
return 0;
} 移动撤销
题意: 初始在,给定移动的序列,问移动完所在点的坐标。
数据范围:
题解:
用一个数组记录所走的还没被撤销的序列,
表示当前所在点是已经走过的第几个点。若是
就正常按照方向走,然后更新
数组,若是
就判断是否有路可退即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
char s[N];
int la[N];
int n, last;
int dx[] = {0, -1, 0, 1};
int dy[] = {1, 0, -1, 0};
int id(char ch) {
if(ch == 'W') return 0;
if(ch == 'A') return 1;
if(ch == 'S') return 2;
if(ch == 'D') return 3;
return -1;
}
int main()
{
scanf("%d", &n);
scanf("%s", s);
last = -1;
int x = 0, y = 0;
for(int i = 0; i < n; ++i) {
if(s[i] == 'Z') {
if(~last) {
x -= dx[la[last]], y -= dy[la[last]];
--last;
}
}
else {
la[++last] = id(s[i]);
x += dx[la[last]], y += dy[la[last]];
}
}
printf("%d %d\n", x, y);
} 石头剪刀布
题意: 给定牛牛和牛妹所出的石头剪刀和布的次数,问牛牛最多可以赢多少分。
题解: 考虑牛牛的石头剪刀和布可以赢牛妹对应的箭头布和石头多少次,这里是得分两次的情况,考虑完后删除,再考虑牛牛和牛妹对应可以打平的次数,这里打平一次得一分,即为最终答案。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n; cin >> n;
int a[2], b[2], c[2];
cin >> a[1] >> b[1] >> c[1];
cin >> a[2] >> b[2] >> c[2];
int res = 0;
int mn = min(a[1], b[2]);
res += mn * 2;
a[1] -= mn, b[2] -= mn;
mn = min(b[1], c[2]);
res += mn * 2;
b[1] -= mn, c[2] -= mn;
mn = min(c[1], a[2]);
res += mn * 2;
c[1] -= mn, a[2] -= mn;
res += min(a[1], a[2]) + min(b[1], b[2]) + min(c[1], c[2]);
cout << res << "\n";
return 0;
} 夹缝中求和
题意: 给定序列,问
的数对个数,其中
。
数据范围:
题解: 考虑枚举的时候,只在其左边枚举
。此时左边的
需满足
。经典树状数组,先离散化然后再枚举每个
即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = N * 3;
int a[N], n, x ,y;
int tr[M];
vector<int> b;
void add(int p, int x) {
for(int i = p; i < M; i += (i & -i)) tr[i] += x;
}
int sum(int p) {
int res = 0;
for(int i = p; i >= 1; i -= (i & -i)) res += tr[i];
return res;
}
int get(int x) {
return lower_bound(b.begin(), b.end(), x) - b.begin() + 1;
}
int main()
{
scanf("%d%d%d", &n, &x, &y);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for(int i = 1; i <= n; ++i) {
b.push_back(a[i]);
b.push_back(x - a[i]);
b.push_back(y - a[i]);
}
sort(b.begin(), b.end());
b.erase(unique(b.begin(), b.end()), b.end());
long long res = 0;
for(int i = 1; i <= n; ++i) {
int l = get(x - a[i]);
int r = get(y - a[i]);
res += sum(r) - sum(l - 1);
add(get(a[i]), 1);
}
printf("%lld\n", res);
return 0;
}
查看3道真题和解析