本文同步发表在 hexo 博客
ARC116A - Odd vs Even
给定 T T T( T ≤ 2 × 1 0 5 T\le 2\times 10^5 T≤2×105)个正整数 n n n( 1 ≤ n ≤ 1 0 18 1\le n\le 10^{18} 1≤n≤1018),问 n n n 的奇约数多还是偶约数多。(约数均为正约数)
很明显,如果 n m o d 2 = 1 n\bmod 2 = 1 nmod2=1,则答案为奇约数多。
否则考察约数们怎么来的。对于一个偶数 n n n 我们总能将其这样拆分: n = 2 k × p n = 2^k\times p n=2k×p( p p p 为奇数)。那么如果 k = 1 k = 1 k=1,则不难发现奇偶约数一样多,否则肯定是偶约数多。
ARC116B - Products of Min-Max
给定一含正整数的集合
A
A
A,求
∑
S
⊆
A
max
a
∈
S
{
a
}
min
a
∈
S
{
a
}
m
o
d
998244353
\sum_{S\subseteq A}\max_{a\in S}\lbrace a\rbrace\min_{a\in S}\lbrace a\rbrace\bmod{998244353}
S⊆A∑a∈Smax{a}a∈Smin{a}mod998244353
的值。
比较妙的题。
首先考虑把最大值和最小值拎出来考虑贡献:将其 A A A 从小到大排序。
然后假设此时
i
<
j
i<j
i<j,则
a
i
≤
a
j
a_i\le a_j
ai≤aj,这一对元素贡献的子集个数为
2
j
−
i
−
1
2^{j - i - 1}
2j−i−1。所以答案就为
∑
i
=
1
n
−
1
∑
j
=
i
+
1
n
a
i
a
j
⋅
2
j
−
i
+
∑
i
=
1
n
a
i
2
\sum_{i = 1}^{n - 1}\sum_{j = i + 1}^na_ia_j\cdot2^{j - i} + \sum_{i = 1}^na_i^2
i=1∑n−1j=i+1∑naiaj⋅2j−i+i=1∑nai2
化简下来可以得到
∑
i
=
1
n
−
1
(
a
i
⋅
2
−
i
∑
j
=
i
+
1
n
a
j
⋅
2
j
−
1
)
+
∑
i
=
1
n
a
i
2
\sum_{i = 1}^{n - 1}\left(a_i\cdot 2^{-i}\sum_{j = i + 1}^na_j\cdot2^{j - 1}\right) + \sum_{i = 1}^na_i^2
i=1∑n−1(ai⋅2−ij=i+1∑naj⋅2j−1)+i=1∑nai2
预处理
a
i
2
i
−
1
a_i2^{i - 1}
ai2i−1 的后缀和就可以直接做了,复杂度
O
(
n
log
n
)
O(n\log n)
O(nlogn)。
#include <cstdio>
#include <cctype>
#include <algorithm>
#define FOR(i, a, b) for (int i = a; i <= b; ++i)
#define DEC(i, a, b) for (int i = a; i >= b; --i)
typedef long long ll;
ll read()
{
ll s = 0, x = 0;
char c = getchar();
while (!isdigit(c))
x |= (c == '-'), c = getchar();
while (isdigit(c))
s = s * 10 + c - '0', c = getchar();
return x ? -s : s;
}
const ll mod = 998244353;
const int maxn = 2e5 + 5;
int n;
ll a[maxn], pow2[maxn], s[maxn];
ll inv(ll a)
{
ll b = mod - 2, ret = 1;
for (; b; b >>= 1, a = a * a % mod)
if (b & 1) ret = ret * a % mod;
return ret;
}
int main()
{
n = read();
pow2[0] = 1;
FOR(i, 1, n) a[i] = read(), pow2[i] = pow2[i - 1] * 2 % mod;
std::sort(a + 1, a + n + 1);
DEC(i, n, 1) s[i] = (s[i + 1] + pow2[i - 1] * a[i] % mod) % mod;
ll ans = 0;
FOR(i, 1, n - 1)
ans = (ans + inv(pow2[i]) * a[i] % mod * s[i + 1] % mod) % mod;
FOR(i, 1, n) ans = (ans + a[i] * a[i] % mod) % mod;
printf("%lld\n", ans);
return 0;
}
ARC116C - Multiple Sequences
给定 n n n 和 m m m( 1 ≤ n , m ≤ 2 × 1 0 5 1\le n,m\le 2\times 10^5 1≤n,m≤2×105),求满足下列条件的长度为 n n n 的整数序列 A A A 的个数。
- 1 ≤ A i ≤ m 1\le A_i\le m 1≤Ai≤m
- A i + 1 A_{i + 1} Ai+1 为 A i A_i Ai 的整数倍
结果模 998244353 998244353 998244353。
很妙的计数题。
考虑从
1
1
1 到
m
m
m 枚举
A
n
A_n
An 的值。我们可以发现其就是把
A
n
A_n
An 每个质因子给安排在
n
n
n 个不同的位置上,求方案数。但是此时需要对每个质因子分开考虑,假设
A
n
=
∏
p
i
c
i
A_n = \prod p_i^{c_i}
An=∏pici,则我们需要对每个质因子都用插板法然后再乘起来得到总方案,即
f
(
A
n
)
=
∏
(
n
+
c
i
−
1
c
i
)
f(A_n) = \prod\binom{n + c_i - 1}{c_i}
f(An)=∏(cin+ci−1)
最后把所有的结果加起来即为答案。
#include <cstdio>
#include <cctype>
#include <vector>
#define FOR(i, a, b) for (int i = a; i <= b; ++i)
#define DEC(i, a, b) for (int i = a; i >= b; --i)
const int maxn = 3e5 + 5, mod = 998244353;
int read()
{
int s = 0, x = 0;
char c = getchar();
while (!isdigit(c))
x |= (c == '-'), c = getchar();
while (isdigit(c))
s = s * 10 + c - '0', c = getchar();
return x ? -s : s;
}
typedef long long ll;
ll n, m;
ll qpow(ll a)
{
ll b = mod - 2, ret = 1;
for (; b; b >>= 1, a = 1ll * a * a % mod)
if (b & 1) ret = 1ll * ret * a % mod;
return ret;
}
ll fact[maxn], inv[maxn];
ll binom(int n, int k)
{
return fact[n] * inv[k] % mod * inv[n - k] % mod;
}
void init()
{
fact[0] = 1;
FOR(i, 1, maxn - 1) fact[i] = i * fact[i - 1] % mod;
inv[maxn - 1] = qpow(fact[maxn - 1]);
DEC(i, maxn - 2, 0) inv[i] = (i + 1) * inv[i + 1] % mod;
return;
}
int main()
{
n = read(), m = read();
init();
ll ans = 0;
FOR(i, 1, m)
{
int now = i;
std::vector<int> tmp;
for (int p = 2; p * p <= now && now != 1; ++p)
{
if (now % p) continue;
int cnt = 0;
while (now % p == 0)
++cnt, now /= p;
tmp.push_back(cnt);
}
if (now != 1) tmp.push_back(1);
ll t = 1;
for (auto c : tmp)
t = t * binom(n + c - 1, c) % mod;
ans = (ans + t) % mod;
}
printf("%d\n", ans);
return 0;
}