# C

# 题目大意

给定 aann,请问 1n1 \to n 中,有多少个数,在十进制和 aa 进制下同时都是回文数

# 数据范围

  • 2a92 \le a \le 9
  • 1 \le n \le 10^

# 题解

这题显然不能暴力枚举 1n1 \to n,可以发现,101210^{12} 内的回文数大概有 10610^{6} 数量级的回文数,不妨考虑预处理好,然后遍历判断其是否是 aa 进制

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
int n, a;
vector<int> hw;

int to_num(string s) {
int res = 0;
for (int i = 0; i < s.size(); i++)
res *= 10, res += (s[i] - '0');
return res;
}

void solve () {
cin >> a >> n;

int ans = 0;

for (auto num : hw) {
if (num > n)
break;

int t = num;
string res = "";

while (num >= a)
res += to_string(num % a), num /= a;

if (num)
res += to_string(num);

string res1 = res;

reverse(res1.begin(), res1.end());
if (res1 == res)
ans += t;
}

cout << ans << '\n';
}

signed main () {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int _ = 1;
// cin >> _;


for (int i = 1; i <= 999999; i++) {
// 偶数回文数
string s = to_string(i), rs = s;
reverse(rs.begin(), rs.end());

hw.push_back(to_num(s + rs));
if (rs.size() > 1)
hw.push_back(to_num(s + rs.substr(1)));
else
hw.push_back(to_num(s));
}

sort(hw.begin(), hw.end());

while (_--)
solve();

return 0;
}

如果要预处理 NN 以内的回文数,可以遍历 1N1 \to \sqrt{N},通过奇数、偶数长度的反转来实现预处理回文数

# D

# 题目大意

现在有 nn 座房子,分别位于 x1xnx_1 \to x_n,你需要在数轴上任意放置 mm 所基站,基站的信号强度如果是 tt 的话,那它只能影响到左右距离不超过 t2\frac{t}{2} 的房子,请问,信号强度和的最小值是多少

# 数据范围

  • 1MN5×1051 \le M \le N \le 5 \times 10^5
  • 1 \le x_i \le 10^

# 题解

显然,在最优情况下,基站的两个边界是都有房子的,那么题目要安排 mm 个基站,也就是说,会把 mini=1i=naimaxi=1nai\min\limits_{i=1}^{i=n} a_i \to \max\limits_{i=1}^{n} a_i,以 aia_i 为分割,分成了 mm 个块
我们的需求是使得 t\sum t 最小,也就是我们可以让剩余的 m1m-1 个空的长度尽可能大,这样减出来的 t\sum t 就一定会更小

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void solve () {
cin >> n >> m, a = vector<int>(n + 1);

for (int i = 1; i <= n; i++)
cin >> a[i];

if (m >= n) {
cout << 0 << '\n';
return;
}

sort(a.begin() + 1, a.end());

int res = 0;

vector<int> dis;

for (int i = 2; i <= n; i++)
dis.push_back(a[i] - a[i - 1]);

sort(dis.begin(), dis.end());

for (int i = 0; i < n - m; i++)
res += dis[i];

cout << res << '\n';
}

# E

# 题目大意

计算满足以下条件的整数三元组 (a,b,c)(a, b,c) 的个数对 998244353998244353 取模的结果

  • 1a,b,cN1 \le a, b, c \le N
  • a,b,ca,b,c 互不相同
  • a%b=ca \% b = c

# 数据范围

  • 3 \le N \le 10^

# 题解

# 1. 确定 b 的范围

题目要求 a,b,ca,b,c 两两不相同,我们可以讨论一下他们的大小关系

  • a<ba < b 时, a % b = a ,不满足三者不相同
  • a>ba > b 时, a % b = c ,此时 Na>bN \ge a > b,只要满足 b>cb > c,则三者必然两两不相同

Na>b>c1N \ge a > b > c \ge 1 有,b[2,N1]b \in [2, N - 1]

# 2. 计算 a 的个数

Na>b>c1,b[2,N1]N \ge a > b > c \ge 1,b \in [2, N - 1] 有,a[b+1,N]a \in [b+1, N]
因为 a%b=c1a \% b = c \ge 1,所以要排除 aabb 的倍数
也就是

a=kb,k[2,Nb]a = kb,k \in [2, \lfloor{\frac{N}{b}}\rfloor]

所以,aa 的个数是

(N(b+1)+1)(Nb2+1)=NbNb+1(N-(b+1)+1)-(\lfloor{\frac{N}{b}}\rfloor-2+1)=N-b-\lfloor{\frac{N}{b}}\rfloor+1

# 3. 求答案

也就是说,答案是求

b=2N1NbNb+1\sum\limits_{b=2}^{N-1} N-b-\lfloor{\frac{N}{b}}\rfloor+1

显然,这样的话复杂度就爆炸了

b=2N1(Nb+1)b=2N1(Nb)\sum\limits_{b=2}^{N-1}(N-b+1)-\sum\limits_{b=2}^{N-1}(\lfloor{\frac{N}{b}}\rfloor)

左侧可以用等差数列计算和,右侧可以用整除分块

# 整除分块

Nb\lfloor{\frac{N}{b}}\rfloorbb 的某些连续区间内的取值是相同的,我们可以按照 Nb\lfloor{\frac{N}{b}}\rfloor 的值来对 bb 进行分块,贡献是 长度 * 值

对于一个分块的起点 lil_i 而言,其下一个分块的起点应该满足

li+1=min{xx>li,N/x<k}l_{i+1}=\min \{x | x > l_i, \lfloor{N/x}\rfloor < k\}

N/x<k\lfloor{N/x}\rfloor < kL>N/kL > \lfloor{N/k}\rfloor,所以 l[i+1] = min(n / k + 1, N)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int qmi(int a, int b) {
int res = 1;
while (b) {
if (b & 1)
res = res * a % MOD;
a = a * a % MOD, b >>= 1;
}
return res;
}

void solve() {
cin >> n;

int inv2 = qmi(2, MOD - 2);
res = (((n - 2) % MOD) * ((n + 1) % MOD) % MOD) * inv2 % MOD;

int l = 2;
while (l < n) {
int k = n / l;
int ll = min(n / k + 1, n);
int cnt = ll - l;

res = (res + MOD - ((k % MOD) * (cnt % MOD) % MOD)) % MOD;
l = ll;
}

cout << res << "\n";
}

遇到 i=1n常数i\sum\limits_{i=1}^{n} \lfloor{\frac{常数}{i}}\rfloor 时,可以考虑用整数分块的思想,整数分块求和的时间复杂度是 O(n)O(\sqrt{n})

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

duoxichangan 微信支付

微信支付

duoxichangan 支付宝

支付宝