Problem A Newbie
来源:第46届ICPC-ECFinal(东亚赛区总决赛) I 题 Future Coder
考察:思维,分类讨论
难度:橙题
本题大致思路是先将数组排序,排序后进行分类讨论。
- 若当前 a 选的数为负数,那么我们另一个数 b 只有 3 种选择的可能,分别是负数,0,正数,当 b 为负数时,可以发现乘法中负负得正,因此 a * b 恒大于 a + b,不符合条件;当 b 为 0 时,a * 0 永远为 0,而 a + 0 永远为负数,因此 a * b 恒大于 a + b,也不符合条件;当 b 为正数时,a * b 永远是负数,并且相乘后只会比原来的 a 更小,而 a + b 由于 b 是正数,因此 相加后只会比原来的 a 更大。因此 a * b < a + b。也就是说,当 a 选择负数时,方案种类即为正数的个数。
- 若当前 a 选的数为 0,同样 b 也有 3 种可能,分别是负数,0,正数。而刚才我们已经讨论了 0 和 负数 的情况,因此只分析其他两种。当 b 为 0 时,a * b = 0,a + b = 0,因此 a * b == a + b,不符合条件;当 b 为正数时,a * b = 0 ,a + b > 0,因此 a * b < a + b 符合条件。因此当 a 为 0 时,方案种数即为正数的个数。
- 若当前 a 选的数为 正数,同样 b 也有 3 种可能,分别是负数,0,正数。而刚才我们已经讨论了 负数 和 正数 以及 0 和 正数 的情况,因此只分析剩下的一种。当 b 为正数时,可以列出一下证明。
当
时,
分别为何值时,满足不等式
。
将 a + b 移相。
做差配上 1
合并式子
因此通过式子可以发现,当 a 为 1 时式子满足 或 当 b 为 1 时式子满足 或 当 a 和 b 均为 1 时式子满足,换句话说,只要 a 或 b 其中任意一个为 1 ,即可满足式子。
因此,当 a 选正数时,我们可以让 a 选 1,若a = 1,则 b 可以为任何正数,因此方案数为剩余正数个数,若 a 不为 1,那么我们应该让 b 为 1。这样就可以求出所有方案了。
这个题实际上可以不用推公式,自己多造几组数据,就可以发现这个原则。
发现大家其实都发现了这个规律,但就是算不明白....
ps:赛时发现大家常犯的错误:不开long long,样例没过就直接交送罚时。完全没想到这题 dirt 率如此之高,希望大家以后还是多注意注意细节,尽可能自己捏一些数据验证一下。
#include<bits/stdc++.h>
#define endl '\n'
typedef long long ll;
const ll mod = 1e9 + 7;
using namespace std;
ll a[2020200];
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
sort(a + 1, a + 1 + n);
ll sum = 0;
for (int i = 1; i <= n; i++) {
if (a[i] <= 0) {
int pos = lower_bound(a + 1 + i, a + 1 + n, 1) - a; //找到 1 所在的位置,也就是正数所在的第一个位置
if (pos == n && a[pos] <= 0) { // 若没有正数,那么此轮无方案
continue;
}
else {
sum += n - pos + 1; // 否则加上正数区间个数
}
}
else if (a[i] == 1) {
sum += n - i; //如果当前为 1,那么除了该位置以外的后面所有的位置都可以被当成 b
}
}
cout << sum << endl;
}
return 0;
}
Problem D 量角器
来源:AcWing 第 61 场周赛 B 题 指针
考察:dfs
难度:橙题
本题可以发现数据范围不超过 15,那么对于这种选数的题,我们可以直接dfs暴力求解即可。不难发现每次拨动我们可以任意选择顺时针或者逆时针,因此直接记录一下顺时针逆时针分别一共转了多少度,当n次拨动完后,判断一下是否相等即可,但是!!!!还有一点要注意,因为量角器是360度的,因此当你转动大于360后,实际上是不存在这种度数的,因此需要判断一下总转动度数对360取余后是否相等即可。
另外这题与上周的C题是极其相似的,除了相等情况的判定,其他几乎一模一样。还是希望大家赛后认认真真补题吧,不懂的可以问。
ps:由于数据有点水,赛时让两位同学代码水过去了,错误原因也正是大于360的情况。
#include<bits/stdc++.h>
#define endl '\n'
typedef long long ll;
const ll mod = 998244353;
using namespace std;
int a[200];
int vis[200];
int n;
int f = 0;
void dfs(int x, int y, int now) { //x记录顺时针,y记录逆时针
if (now == n + 1) {
if (x % 360 == y % 360) {
f = 1;
}
return;
}
dfs(x + a[now], y, now + 1);
dfs(x, y + a[now], now + 1);
}
int main() {
cin >> n;
ll sum = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
sum += a[i];
}
dfs(0, 0, 1);
if (f) {
cout << "YES";
}
else {
cout << "NO";
}
return 0;
}