基本情况
脑子太不清楚了。
A题有思路,但是各种细节问题(数论题太不熟练了),错了好几次才过。
B题直接分析数据愣猜一个解,猜对了。
A. Burenka Plays with Fractions
难点在分析输出 \(1\) 的情况。
我的想法是通分,然后直接比分子是否互相整除,想法很对,但是实现一直犯病。
-
本意是为了防止爆
long long
所以先对两个分数约分一下,但是这样写代码,第一次 \(a\) 除完gcd
之后,第二次求得gcd(a,b)
明显就不是原来的了啊!。a /= gcd(a, b); b /= gcd(a, b); c /= gcd(c, d); d /= gcd(c, d);
修改过后
ll gcd_1 = gcd(a, b), gcd_2 = gcd(c, d); a /= gcd_1; b /= gcd_1; c /= gcd_2; d /= gcd_2;
-
通分更是重量级
a *= lcm(b, d); c *= lcm(b, d)
经典胡言乱语,两个分子光乘分母的最小公倍数是在做什么?肯定要除去对应地分母啊。
a *= lcm(b, d) / b; c *= lcm(b, d) / d;
终于AC。
void solve()
{
ll a, b, c, d;
std::cin >> a >> b >> c >> d;
if (a * d == b * c) {std::cout << 0 << std::endl; return ;}
if (a == 0 || c == 0) {std::cout << 1 << std::endl; return ;}
ll gcd_1 = gcd(a, b), gcd_2 = gcd(c, d);
a /= gcd_1; b /= gcd_1; c /= gcd_2; d /= gcd_2;
a *= lcm(b, d) / b; c *= lcm(b, d) / d;
if (a % c == 0 || c % a == 0) {std::cout << 1 << std::endl; return ;}
std::cout << 2 << std::endl; return ;
}
B. Interesting Sum
猜的解法,不会证明:
void solve()
{
int n; std::cin >> n;
std::vector<int> a(n + 10);
for (int i = 1; i <= n; i++) std::cin >> a[i];
std::sort(a.begin() + 1, a.begin() + n + 1);
std::cout << a[n] + a[n - 1] - a[1] - a[2] << std::endl;
}
证明如下:
思考正解,要让原式最大,就要让两个 \(\max\) 得到的值最大,\(\min\) 得到的值最小。
什么最大?什么最小?当然是最大、次大、最小、次小这四个值!
这时有人要问了:你怎么保证一定能把这四个值分成符合条件的两组呢?
干脆枚举,简洁明了。设最大、次大、最小、次小分别是 \(a,b,c,d\)。
- \(abcd\),可以变成 \(a|bc|d\)。
- \(abdc\),可以变成 \(a|bd|c\)。
- \(adbc\),可以变成 \(|ad|bc\)。
- \(\cdots\)
这说明了我们的猜想是正确的(实际上这就是分割一个环)。
就这样得到最优的 \(O(n)\) 做法,输出 \(a+b-c-d\) 即可。
标签:std,gcd,Codeforces,最小,Div,lcm,815,cout From: https://www.cnblogs.com/kdlyh/p/17908988.html