前言
题解
VP了这场比赛,整体还是偏简单,最难的题是数论相关,算一道思维题。
也看了赛时榜单,除了数论,大模拟和图论题也是拦路虎。
打工人
有趣的一道数学题,有点绕
很像数列和
∑ i = 1 i = n i = n ∗ ( n + 1 ) / 2 \sum_{i=1}^{i=n} i=n*(n+1)/2 i=1∑i=ni=n∗(n+1)/2
从公式结合时间复杂度,可以 n \sqrt n n 求解单次查询,时间复杂度 O ( q ∗ n ) O(q * \sqrt n) O(q∗n )是可行的。
对于区间 [ L , R ] [L, R] [L,R]问题,转化为函数差
f ( x ) = [ 1 , x ] 的累加和 f(x) = [1, x]的累加和 f(x)=[1,x]的累加和
g ( l , r ) = f ( r ) − f ( l − 1 ) g(l, r) = f(r) - f(l - 1) g(l,r)=f(r)−f(l−1)
关键在于如何求解这个函数 f ( x ) f(x) f(x)
cpp
#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
// 时间复杂度为O(\sqrt n)
int64 f(int v) {
int64 r = 0;
int acc = 0;
for (int i = 1; acc <= v; i++) {
r += (i * min(v - acc, i));
acc += i;
}
return r;
}
int main() {
int q;
cin >> q;
while (q-- > 0) {
int l, r;
cin >> l >> r;
int64 r1 = f(l - 1);
int64 r2 = f(r);
cout << r2 - r1 << endl;
}
return 0;
}
当然这题是可以把单次查询优化为 O ( 1 ) O(1) O(1)的
P序列
其实是一道思维题。
可以从构造的角度,去解这道题,就会发现很容易。
因为其是一种山峰状的数组, 左侧非严格递增,右侧非严格递减。
对数进行分组,按值排序,然后放置于数组。
- 最大值先放于中间
- 按序依次放置其他数 v i v_i vi,若个数为 c n t v i cnt_{v_i} cntvi,其放置左右侧的方案数总共为 c n t v i + 1 cnt_{v_i} + 1 cntvi+1
根据乘法原理,最终的总方案数为
∏ ( c n t v i + 1 ) , v i ≠ v m a x {\prod (cnt_{v_i} + 1), v_i \ne v_{max}} ∏(cntvi+1),vi=vmax
cpp
#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
int64 mod = 998244353l;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
map<int, int> hp;
int mz = -0x3f3f3f3f;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
hp[x]++;
mz = max(mz, x);
}
long long res = 1l;
for (auto &[k, v] : hp) {
if (k != mz) {
res = res * (v + 1) % mod;
}
}
cout << res << endl;
return 0;
}
多项式输入
思路: 模拟
对于这类模拟题,最好的方式是拆分
多项式和拆分成
- 符号
- 系数
- 指数
这三部分,然后分别处理,这样就会很清晰。
然后这边需要加入一个特例
就是全是 0 的情况 就是全是0的情况 就是全是0的情况
cpp
#include<bits/stdc++.h>
using namespace std;
int main( )
{
int n;
cin >> n;
vector<int> vec(n + 1);
for (int &x: vec) cin >> x;
string s;
bool first = true;
for (int i = 0; i <= n; i++) {
if (vec[i] == 0) continue;
// 1. 处理符号
if (first) {
s.append(vec[i] > 0 ? "": "-");
} else {
s.append(vec[i] > 0 ? "+" : "-");
}
// 2. 系数部分
int x = abs(vec[i]);
if (i != n && x > 1) {
s.append(to_string(x));
} else if (i == n) {
s.append(to_string(x));
}
// 3. 指数部分
if (i < n - 1) {
s.append("x^");
s.append(to_string(n - i));
} else if (i == n - 1) {
s.append("x");
}
first = false;
}
// 特别处理0这个特例
if (s.length() == 0) {
s = "0";
}
cout << s << endl;
return 0;
}