AtCoder Regular Contest 158 题解
题面:https://atcoder.jp/contests/arc158/tasks_print
A - +3 +5 +7
将 \(+3,+5,+7\) 可以在不改变相对位置的情况下都 \(-5\),即变成 \(-2,+0,+2\),发现和不变,可以得出最后的数的值 \(x=\dfrac{a+b+c}{3}\),如果 \(x\) 不是整数就无解。发现答案为 \(\dfrac{|a-x|+|b-x|+|c-x|}{4}\),如果不是整数也无解。
注:计算过程中有任何不满足实际意义的都算无解。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
#define rep(i, a, b) for(int i = a;i <= b; ++ i)
#define per(i, b, a) for(int i = b;i >= a; -- i)
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) {return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;}
#define int long long
namespace fastIO {
template < typename T > void read (T &x) {x = 0; T flag = 1; char c = getchar (); for ( ; c < '0' || c > '9' ; c = getchar ()) flag = (c == '-') ? -1 : flag; for ( ; c >= '0' && c <= '9' ; c = getchar ()) x = (x << 1) + (x << 3) + (c ^ 48); x *= flag;}
template < typename T, typename ...T1 > void read (T &x, T1 &...x1) {read (x); read (x1...);}
template < typename T > void write (T x) {if (x < 0) {x = -x; putchar ('-');} if (x / 10) {write (x / 10);} putchar (x % 10 + '0');}
template < typename T > void writesp (T x) {write (x); putchar (' ');}
template < typename T > void writeln (T x) {write (x); putchar ('\n');}
}
using namespace fastIO;
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
signed main () {
int T; read (T);
while (T --) {
int a, b, c;
read (a, b, c);
int avg = (a + b + c) / 3;
if ((a + b + c) % 3) {
puts ("-1");
continue;
}
int da = avg - a;
int db = avg - b;
int dc = avg - c;
if (da + db + dc) {
puts ("-1");
continue;
}
if (abs (da) & 1) {puts ("-1"); continue;}
if (abs (db) & 1) {puts ("-1"); continue;}
if (abs (dc) & 1) {puts ("-1"); continue;}
da = max (da, -da);
db = max (db, -db);
dc = max (dc, -dc);
da /= 2, db /= 2, dc /= 2;
if ((da + db + dc) & 1) {
puts ("-1");
continue;
}
writeln ((da + db + dc) / 2);
}
return 0;
}
B - Sum-Product Ratio
发现 \(x\) 只可能从 \(a\) 中最大的三个和最小的三个取,枚举即可。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
#define rep(i, a, b) for(int i = a;i <= b; ++ i)
#define per(i, b, a) for(int i = b;i >= a; -- i)
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) {return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;}
#define int long long
namespace fastIO {
template < typename T > void read (T &x) {x = 0; T flag = 1; char c = getchar (); for ( ; c < '0' || c > '9' ; c = getchar ()) flag = (c == '-') ? -1 : flag; for ( ; c >= '0' && c <= '9' ; c = getchar ()) x = (x << 1) + (x << 3) + (c ^ 48); x *= flag;}
template < typename T, typename ...T1 > void read (T &x, T1 &...x1) {read (x); read (x1...);}
template < typename T > void write (T x) {if (x < 0) {x = -x; putchar ('-');} if (x / 10) {write (x / 10);} putchar (x % 10 + '0');}
template < typename T > void writesp (T x) {write (x); putchar (' ');}
template < typename T > void writeln (T x) {write (x); putchar ('\n');}
}
using namespace fastIO;
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
int n, a[200005], pos[200005], neg[200005], np, nn;
long double mx, mn;
inline void upd (long double tmp) {
if (mx - tmp < 1e-18) mx = tmp;
if (mn - tmp > 1e-18) mn = tmp;
}
inline int pos_up_sum (int x) {int s = 0; rep (i, 1, x) s += pos[np - i + 1]; return s;}
inline int pos_down_sum (int x) {int s = 0; rep (i, 1, x) s += pos[i]; return s;}
inline int neg_up_sum (int x) {int s = 0; rep (i, 1, x) s += neg[nn - i + 1]; return s;}
inline int neg_down_sum (int x) {int s = 0; rep (i, 1, x) s += neg[i]; return s;}
inline int pos_up_pd (int x) {int s = 1; rep (i, 1, x) s *= pos[np - i + 1]; return s;}
inline int pos_down_pd (int x) {int s = 1; rep (i, 1, x) s *= pos[i]; return s;}
inline int neg_up_pd (int x) {int s = 1; rep (i, 1, x) s *= neg[nn - i + 1]; return s;}
inline int neg_down_pd (int x) {int s = 1; rep (i, 1, x) s *= neg[i]; return s;}
signed main () {
read (n);
rep (i, 1, n) read (a[i]);
rep (i, 1, n) {
if (a[i] > 0) pos[++ np] = a[i];
else neg[++ nn] = a[i];
}
sort (pos + 1, pos + 1 + np);
sort (neg + 1, neg + 1 + nn);
mx = -1e100;
mn = 1e100;
rep (i, 0, 3) {
int j = 3 - i;
if (np >= i && nn >= j) {
rep (k1, 0, i) {
rep (k2, 0, j) {
upd ((long double) (pos_up_sum (k1) + pos_down_sum (i - k1) + neg_up_sum (k2) + neg_down_sum (j - k2)) / (long double) (pos_up_pd (k1) * pos_down_pd (i - k1) * neg_up_pd (k2) * neg_down_pd (j - k2)));
}
}
}
}
printf ("%.12Lf\n%.12Lf\n", mn, mx);
return 0;
}
C - All Pair Digit Sums
突破口:每次进位会将数位和减去 \(9\)。
设 \(g(a,b)\) 为计算 \(a+b\) 时的进位次数。
则:\(f(a+b)=f(a)+f(b)-9\times g(a,b)\)。
至于 \(g\) 函数,我们可以将每一位拆开,对每一位 \(k=0,1,\dots\),如果 \(a \bmod 10^{k+1}+b\bmod 10^{k+1} \geq 10^{k+1}\),则进位次数加 \(1\),答案减去 \(9\)。
具体实现用二分可以做到 \(O(16 n \log n)\)。
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) {return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;}
#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
const int N = 200005;
int n, a[N], ans;
struct qwq {
int pri;
int val;
} b[N];
inline bool cmp (qwq p1, qwq p2) {
return p1.pri < p2.pri;
}
inline int sum (int x) {
int res = 0;
while (x) {
res += x % 10;
x /= 10;
}
return res;
}
signed main () {
scanf ("%lld", &n);
for (int i = 1;i <= n; ++ i) scanf ("%lld", &a[i]), ans += sum (a[i]);
ans *= 2 * n;
int tmp = 1;
for (int i = 0;i <= 15; ++ i) {
tmp *= 10;
for (int j = 1;j <= n; ++ j) b[j].val = a[j], b[j].pri = a[j] % tmp;
sort (b + 1, b + 1 + n, cmp);
for (int j = 1;j <= n; ++ j) {
if (b[n].pri + b[j].pri < tmp) ;
else {
int L = 1, R = n;
while (R - L > 1) {
int mid = L + R >> 1;
if (b[mid].pri + b[j].pri >= tmp) R = mid;
else L = mid;
}
if (b[L].pri + b[j].pri >= tmp) ans -= 9 * (n - L + 1);
else ans -= 9 * (n - R + 1);
}
}
}
printf ("%lld\n", ans);
return 0;
}
D - Equation
我们考虑随机答案。
每次随机出 \(a,b,c\),成功的概率在 \(p\) 很大的时候微乎其微。
考虑调整 \(a,b,c\),设 \(f=(a+b+c)(a^n+b^n+c^n)(a^{2n}+b^{2n}+c^{2n}),g=a^{3n}+b^{3n}+c^{3n}\)。
我们调整目标就是让 \(f=g\)。
考虑将 \(a,b,c\) 都乘以 \(t\)。
设 \(f',g'\) 为新的 LHS & RHS, 则 \(f'=t^{3n+1}f,g'=t^{3n}g\)。
若 \(f'=g'\),则:\(t=\dfrac{g}{f}\),只要满足 \(f\bmod p,g \bmod p>0\) 即可。
这样一次成功的概率就大大增加了。
感觉题目的一切都是为题解准备的。(要不 \(p\) 是质数)
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
typedef long long ll;
typedef pair < int, int > PII;
typedef int itn;
mt19937 RND_MAKER (chrono :: steady_clock :: now ().time_since_epoch ().count ());
inline ll randomly (const ll l, const ll r) {return (RND_MAKER () ^ (1ull << 63)) % (r - l + 1) + l;}
#define int long long
const double pi = acos (-1);
//__gnu_pbds :: tree < Key, Mapped, Cmp_Fn = std :: less < Key >, Tag = rb_tree_tag, Node_Upadte = null_tree_node_update, Allocator = std :: allocator < char > > ;
//__gnu_pbds :: tree < PPS, __gnu_pbds :: null_type, less < PPS >, __gnu_pbds :: rb_tree_tag, __gnu_pbds :: tree_order_statistics_node_update > tr;
int n, p;
inline int pow_mod (int a, int b, int p) {
int res = 1;
while (b) {
if (b & 1) res = res * a % p;
b >>= 1;
a = a * a % p;
}
return res;
}
signed main () {
int _;
scanf ("%lld", &_);
while (_ --) {
scanf ("%lld %lld", &n, &p);
while (true) {
int x, y, z;
x = randomly (1, p - 1);
if (x + 1 >= p) continue;
y = randomly (x + 1, p - 1);
if (y + 1 >= p) continue;
z = randomly (y + 1, p - 1);
int xn = pow_mod (x, n, p);
int yn = pow_mod (y, n, p);
int zn = pow_mod (z, n, p);
int x2n = xn * xn % p;
int y2n = yn * yn % p;
int z2n = zn * zn % p;
int x3n = xn * x2n % p;
int y3n = yn * y2n % p;
int z3n = zn * z2n % p;
int LHS = (x + y + z) % p * (xn + yn + zn) % p * (x2n + y2n + z2n) % p;
int RHS = (x3n + y3n + z3n) % p;
if (LHS == RHS) {
printf ("%lld %lld %lld\n", x, y, z);
break;
}
if (LHS && RHS) {
int t = RHS * pow_mod (LHS, p - 2, p) % p;
vector < int > qwq;
qwq.clear ();
qwq.push_back (x * t % p);
qwq.push_back (y * t % p);
qwq.push_back (z * t % p);
sort (qwq.begin (), qwq.end ());
printf ("%lld %lld %lld\n", qwq[0], qwq[1], qwq[2]);
break;
}
}
}
return 0;
}