2022 icpc杭州站 A. Modulo Ruins the Legend
思路
题目可以转换为求 ( s ⋅ n + d t ⋅ n ( n + 1 ) 2 + s u m ) % m ( 1 ) (s \cdot n + d_t \cdot \frac{n(n + 1)}{2} + sum) \% m (1) (s⋅n+dt⋅2n(n+1)+sum)%m(1) 的最小值
d = g c d ( n , n ( n + 1 ) 2 ) d = gcd(n,\frac{n(n + 1)}{2}) d=gcd(n,2n(n+1))
于是
(
1
)
(1)
(1) 转换为
(
k
⋅
d
+
s
u
m
)
%
m
=
(
k
⋅
d
%
m
+
s
u
m
%
m
)
%
m
=
(
k
⋅
d
+
t
⋅
m
+
s
u
m
%
m
)
%
m
g
=
g
c
d
(
d
,
m
)
,
k
⋅
d
+
t
⋅
m
=
z
⋅
g
,
s
u
m
2
=
s
u
m
%
m
=
(
z
⋅
g
+
s
u
m
2
)
%
m
\begin{aligned}(k \cdot d + sum) \% m &= (k\cdot d \%m + sum \%m) \%m \\&=(k\cdot d + t\cdot m + sum \%m) \%m \\&g = gcd(d, m), k\cdot d + t\cdot m = z\cdot g, \ sum_2 = sum \% m\\&=(z \cdot g + sum_2) \% m\end{aligned}
(k⋅d+sum)%m=(k⋅d%m+sum%m)%m=(k⋅d+t⋅m+sum%m)%mg=gcd(d,m),k⋅d+t⋅m=z⋅g, sum2=sum%m=(z⋅g+sum2)%m
因为
g
≤
m
,
s
u
m
2
<
m
g \le m, sum_2 < m
g≤m,sum2<m, 所以
z
⋅
g
≥
m
−
s
u
m
2
z \cdot g \ge m - sum_2
z⋅g≥m−sum2 时候能得到最小值,
z
=
⌈
m
−
s
u
m
2
g
⌉
z = \lceil \frac{m - sum_2}{g} \rceil
z=⌈gm−sum2⌉
证明:
z ⋅ g + s u m 2 < m z\cdot g + sum_2 < m z⋅g+sum2<m 时, ( z ⋅ g + s u m 2 ) % m (z \cdot g + sum_2) \% m (z⋅g+sum2)%m 中最小都会有一个 g g g
z ⋅ g + s u m 2 > m z\cdot g + sum_2 > m z⋅g+sum2>m 时, ( z ⋅ g + s u m 2 ) % m (z \cdot g + sum_2) \% m (z⋅g+sum2)%m 最小值能够小于 g g g
求出 z 之后,再一步一步的代回去,用 exgcd 求出 s , d t s, d_t s,dt 即可
最小值就是 z ⋅ g + s u m 2 − m z\cdot g + sum_2 - m z⋅g+sum2−m
#include <bits/stdc++.h>
#define endl "\n"
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll exgcd(ll a, ll b, ll& x, ll& y) {
if (!b) {
x = 1, y = 0;
return a;
}
ll d = exgcd(b, a % b, x, y);
ll tx = x;
x = y, y = tx - y * (a / b);
return d;
}
signed main() {
IOS;
ll n, mod; cin >> n >> mod;
ll sum = 0;
for (int i = 1; i <= n; i++) {
ll t; cin >> t;
sum += t;
}
ll a = n, b = n * (n + 1) / 2;
ll s, dt;
ll d = exgcd(a, b, s, dt);
sum %= mod;
ll k, t;
ll g = exgcd(d, mod, k, t);
ll z = (mod - sum + g - 1) / g;
(k *= z) %= mod;
s = ((s % mod * k) % mod + mod) % mod, dt = ((dt % mod * k) % mod + mod) % mod;
cout << (z * g + sum - mod) << endl;
cout << s << " " << dt << endl;
}