闲话
推不推荐学 lct 呢?
最近一直看到的两张图(
我不理解
但我大为震撼
又说到《魔女之旅》
再放假的时候该看了
最近很经常地哼《Aster》
想听想听想听想听想听
杂题
*点开我的评测记录
*空空如也
今天写点啥好呢?
大水题[即答]
求
\[\sum_{i=1}^{n} \sum_{j\neq i}^{m} (n \bmod i) \times (m \bmod j)\pmod {19940417} \]\(1 \leq n,m \leq 10^9\)。
没错就是这道水题。还是早点刷了好(
同时照应一下上文(
主要是为了练习 \(\LaTeX\) 的写法?
\[\begin{aligned} & \sum_{i=1}^{n} \sum_{j\neq i}^{m} (n \bmod i) \times (m \bmod j) \\ = \ & \sum_{i=1}^{n} \sum_{j=1}^{m} (n \bmod i) \times (m \bmod j) - \sum_{i=1}^{n}(n \bmod i) \times (m \bmod i) \\ = \ & \left( \sum_{i=1}^{n} (n \bmod i)\right) \times \left( \sum_{j=1}^{m} (m \bmod j) \right) - \sum_{i=1}^{n}(n \bmod i) \times (m \bmod i) \\ = \ & \left( \sum_{i=1}^{n} n - i\left\lfloor\frac ni \right\rfloor\right) \times \left( \sum_{j=1}^{m} m - i\left\lfloor\frac mi \right\rfloor\right) - \sum_{i=1}^{n}\left(n - i\left\lfloor\frac ni \right\rfloor\right) \times \left(m - i\left\lfloor\frac mi \right\rfloor\right) \\ = \ & \left( n^2 - \sum_{i=1}^{n} i\left\lfloor\frac ni \right\rfloor\right) \times \left( m^2- \sum_{j=1}^{m} i\left\lfloor\frac mi \right\rfloor\right) - \sum_{i=1}^{n}\left( nm - m\times i\left\lfloor\frac ni \right\rfloor - n\times i\left\lfloor\frac mi \right\rfloor + i^2\left\lfloor\frac mi \right\rfloor\left\lfloor\frac ni \right\rfloor\right) \end{aligned}\]然后整除分块一下就能在 \(O(\sqrt n + \sqrt m)\) 的复杂度内做完了
我觉得这题唯一的难点在于写题解时的 \(\LaTeX\)
同时注意一下 19940417 nmd不是质数 你需要欧拉定理来算 6 的逆元
为此我 nmd 调了一个早上
因此我升级了一下我的代码头
加入了编译期的inv2/3/6 (
code
#include <bits/stdc++.h>
using namespace std; using pii = pair<int,int>;
using ll = long long; using ull = unsigned long long; using db = double; using ld = long double; using lll = __int128_t;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
template <typename T> T rand(T l, T r) { return uniform_int_distribution<T>(l, r)(rnd); }
template <typename T> void get(T & x) {
x = 0; char ch = getchar(); bool f = false; while (ch < '0' or ch > '9') f = f or ch == '-', ch = getchar();
while ('0' <= ch and ch <= '9') x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); f && (x = -x);
} template <typename T, typename ... Args> void get(T & a, Args & ... b) { get(a); get(b...); }
template <typename T1, typename T2> T1 min(T1 a, T2 b) { return a < b ? a : b; }
template <typename T1, typename T2> T1 max(T1 a, T2 b) { return a > b ? a : b; }
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define rep(i,s,t) for (register int i = (s), i##_ = (t) + 1; i < i##_; ++ i)
#define pre(i,s,t) for (register int i = (s), i##_ = (t) - 1; i > i##_; -- i)
#define Aster(i, s) for (int i = head[s], v; i; i = e[i].next)
#define all(s) s.begin(), s.end()
const int N = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const ll infll = 0x3f3f3f3f3f3f3f3fll;
const int mod = 19940417;
/* T1(T1, T2) add and sub with return val */ template <typename T1, typename T2> T1 add(T1 a, T2 b) { return (a += b) >= mod ? a - mod : a; } template <typename T1, typename ...Args> T1 add(T1 a, Args ... b) { return add(a, add(b...)); } template <typename T1, typename T2> T1 sub(T1 a, T2 b) { return (a -= b) < 0 ? a + mod : a; } template <typename T1, typename ...Args> T1 sub(T1 a, Args ... b) { return add(a, add(b...)); }
/* int(int, int) mul based on FastMod(lll used) */ struct FastMod { int m; ll b; void init(int _m) { m = _m; if (m == 0) m = 1; b = ((lll)1<<64) / m; } FastMod(int _m) { init(_m); } int operator() (ll a) {ll q = ((lll)a * b) >> 64; a -= q * m; if (a >= m) a -= m; return a; } } Mod(mod); int mul(int a, int b) { return Mod(1ll * a * b); } template <typename T1, typename T2> int mul(T1 a, T2 b) { return Mod((long long)(1ll * a * b)); } template <typename T, typename ...Args> int mul(T a, Args ...b) { return mul(a, mul(b...)); } // /* trivial multiple function(idk whether its useful*/ int mul(int a, int b) { return 1ll * a * b % mod; } template <typename T1, typename T2> int mul(T1 a, T2 b) { return (long long)(1ll * a * b) % mod; } template <typename T, typename ...Args> int mul(T a, Args ...b) { return mul(a, mul(b...)); }
/* useful functions : qp(int, int) */ template <typename T1, typename T2> T1 qp(T1 a, T2 b) { T1 ret = 1; for (; b > 0; a = mul(a, a), b >>= 1) if (b & 1) ret = mul(ret, a); return ret; }
/* inv2, inv3, inv6 with __var_phi = phi(mod) */ constexpr int __var_pow(int a, int b) { int ret = 1; for (; b > 0; b >>= 1, a = 1ll * a * a % mod) if (b & 1) ret = 1ll * ret * a % mod; return ret; } constexpr int __var_phi(int x) { if (x <= 2) return 1; int ret = x; for (int i = 2; 1ll * i * i <= x; ++i) if (x % i == 0) { ret = ret / i * (i - 1); while (x % i == 0) x /= i; } if (x > 1) ret = ret / x * (x - 1); return ret; } const int __phi_mod = __var_phi(mod); const int inv2 = __var_pow(2, __phi_mod - 1), inv3 = __var_pow(3, __phi_mod - 1), inv6 = __var_pow(6, __phi_mod - 1); constexpr int __var_check() { assert( 1ll * 2 * inv2 % mod == 1 ); assert( 1ll * 3 * inv3 % mod == 1 ); assert( 1ll * 6 * inv6 % mod == 1 ); return (unsigned int)(-1); } const int __var_dummy = __var_check();
int n, m, ans, tmp;
#define S(n) (Mod(1ll * (n) * (n + 1) >> 1))
#define S2(n) (mul(n, (n) + 1, ((n) * 2) + 1, inv6))
signed main() {
get(n, m);
ans = mul(n, n);
for (int l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
ans = add(ans, mod - mul(n / l, add(S(r), mod - S(l - 1))));
}
tmp = mul(m, m);
for (int l = 1, r; l <= m; l = r + 1) {
r = m / (m / l);
tmp = add(tmp, mod - mul(m / l, add(S(r), mod - S(l - 1))));
}
ans = mul(ans, tmp);
for (int l = 1, r; l <= min(n, m); l = r + 1) {
r = min(n / (n / l), m / (m / l));
ans = add(ans, mod - mul(r - l + 1, n, m));
ans = add(ans, mul(n, add(S(r), mod - S(l - 1)), m / l), mul(m, add(S(r), mod - S(l - 1)), n / l));
ans = add(ans, mod - mul(add(S2(r), mod - S2(l - 1)), n / l, m / l));
}
cout << ans << endl;
}
给定长为 \(n\) 的字符串 \(S\),其由
<
与>
组成。我们称一个长度为 \(n+1\) 的非负整数序列 \(x=(x_0,x_1,\dots,x_n)\) 是好的,当且仅当对于任意 \(1\le i\le n\),有
- 若 \(S_i\) 为
<
,则 \(x_{i-1} < x_i\);- 若 \(S_i\) 为
>
,则 \(x_{i-1} > x_i\);给定一个好的非负整数序列 \(A\),你需要将其拆分为尽可能多的好的非负整数序列。具体地说,你需要找到正整数 \(k\) 以及 \(k\) 个好的非负整数序列 \(B_1,B_2,\dots,B_k\),满足对于任意 \(0\le i \le n\),\(\sum_{j=1}^k B_{j,i} = A_i\)。
你需要最大化 \(k\) 的值。输出这个值,以及你所构造的 \(k\) 个长度为 \(n + 1\) 的串。
如果有多组解,输出任意一组即可。\(1\le n \le 100, 0\le a_i\le 10^4\)。
普及题。
令 \(d_i = |A_i - A_{i-1}|\)。我们断言,\(k = \min_{i=1}^n d_i\)。
证明:
首先证明 \(k \le \min_{i=1}^n d_i\)。
由 \(B\) 序列的性质,有 \(d_i = \sum_{j=1}^k |B_{j,i} - B_{j,i-1}|\)。由于 \(B\) 是好的,因此在求和项内各项必定 \(>0\)。因此 $ \(d_i = \sum_{j=1}^k |B_{j,i} - B_{j,i-1}| \ge \sum_{j=1}^k 1 = k\)。因此有 \(k \le \min_{i=1}^n d_i\)。
然后证明 \(k\) 可以取到所确定的最大值。
我们可以将 \(A\) 序列的每个值均匀地分给 \(k\) 个 \(B\) 序列。即 \(B_{i,j} = \left\lfloor\frac{A_j + i - 1}k\right \rfloor\)。容易发现通过这样的分法可以使 \(k = \min_{i=1}^n d_i\)。
因此我们证明了断言。
断言同样给出了构造方法,因此我们可以在 \(O(nk)\) 的时间复杂度内完成构造。
所以这题的 S 没用是吧
code
#include <bits/stdc++.h>
using namespace std;
#define rep(i,s,t) for (register int i = (s), i##_ = (t) + 1; i < i##_; ++ i)
int n, a[105], k = 1e9;
char ch[105];
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> ch + 1; rep(i,0,n) cin >> a[i];
rep(i,1,n) k = min(k, abs(a[i] - a[i - 1]));
cout << k << '\n';
rep(i,1,k) {
rep(j,0,n) cout << (a[j] + i - 1) / k << ' ';
cout << '\n';
}
}
有 \(2N\) 张牌,编号为 \(1\sim 2N\),第 \(i\) 张牌价值 \(V_i\)。现在高桥和青木轮流取牌,每次高桥先取一张没有被取过的牌,之后青木取编号为剩余牌编号中位数的牌。重复以上步骤 \(N\) 次,两人各取 \(N\) 张牌。
请求出高桥取到的牌价值之和的最大值。
输入第一行一个整数 \(N\),第二行 \(N\) 个整数 \(V_1,V_2,\cdots,V_N\)。
\(1\leqslant N\leqslant 2\times 10^5\);\(0\leqslant V_i\leqslant 10^9\); $ V_i $ 均为整数。
hhh这样例给的让人容易出假做法 出题人坏的
这题一看就是要计数青木选的数的最小值。毕竟高桥在哪都能选数,但是青木只能选剩下的确定值。
显然有个假做法是从中间开始向两边扫,每次选个最小的加进去。它能过八个点 但是这玩意是acm赛制所以没用
但是青木不一定只能选择当前两个数中的一个
我们发现,当选择到第 \(i\) 个数时,青木可以选择的范围为 \([n - i + 1, n + i]\)。我们可以从中间开始维护两个指针,初始化为 \(n\) 和 \(n + 1\),分别向两边扫描,每次将 \(a_{n-i+1}\) 与 \(a_{n+i}\) 加入一个堆。加入后选择最小值即可。
数学归纳法可以证明做法的正确性。总时间复杂度 \(O(n\log n)\)。
code
#include <bits/stdc++.h>
using namespace std;
#define rep(i,s,t) for (register int i = (s), i##_ = (t) + 1; i < i##_; ++ i)
int n, a[1000005];
long long ans;
priority_queue<int> que;
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n; rep(i,1,n<<1) cin >> a[i], ans += a[i];
for (int p1 = n, p2 = n + 1; p1 > 0; p1 --, p2 ++) {
que.push( - a[p1] ); que.push( - a[p2] );
ans += que.top(); que.pop();
} cout << ans << '\n';
}