题目链接:https://codeforces.com/contest/1604/problem/E
新知识点:
⌊
m
1
⌋
,
⌊
m
2
⌋
,
.
.
.
,
⌊
m
m
⌋
\lfloor\frac{m}{1}\rfloor,\lfloor\frac{m}{2}\rfloor,...,\lfloor\frac{m}{m}\rfloor
⌊1m⌋,⌊2m⌋,...,⌊mm⌋中最多有
2
m
2\sqrt{m}
2m个不同的数。
证明:https://math.stackexchange.com/questions/1069460/how-many-distinct-values-of-floorn-i-exists-for-i-1-to-n
d p ( i , x ) dp(i,x) dp(i,x)为 a [ i ; j ] ( i < = j ) a[i; j](i<=j) a[i;j](i<=j) 在变成合法状态下,以x为起始元素的数组个数。则该值对答案的贡献为 ( i − 1 ) ∗ d p ( i , x ) ∗ ( ⌊ a [ i − 1 ] ⌈ a [ i − 1 ] x ⌉ ⌋ − 1 ) (i - 1)*dp(i, x)*(\lfloor\frac{a[i-1]}{\lceil{\frac{a[i - 1]}{x}}\rceil}\rfloor-1) (i−1)∗dp(i,x)∗(⌊⌈xa[i−1]⌉a[i−1]⌋−1)。
这个 ( i − 1 ) (i-1) (i−1)是很巧妙的,因为这个值的影响,不论前面有多少个数都会有贡献。这个式子中其它的值很好推,在想暴力的写法时就能知道了。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 5;
const int MOD = 998244353;
int t, n;
LL a[N], dp[2][N];
vector<int> v[2];
int main(void) {
// freopen("in.txt", "r", stdin);
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
LL ans = 0, k = 1;
for (int i = n; i > 1; i--) {
k ^= 1;
dp[k][a[i]] += 1;
v[k].push_back(a[i]);
int last = -1;
for (int j = 0; j < v[k].size(); j++) {
int x = v[k][j];
int f = (a[i - 1] + x - 1) / x; // a[i] / x 向上取整
int g = a[i - 1] / f; // floor(a[i]/ceil(a[i]/x))
dp[k ^ 1][g] += dp[k][x];
ans = (ans + dp[k][x] * (i - 1) % MOD * (f - 1) % MOD) % MOD;
if (last != g) {
last = g;
v[k ^ 1].push_back(g);
}
dp[k][x] = 0;
}
v[k].clear();
}
memset(dp, 0, sizeof(dp));
v[0].clear(); v[1].clear();
printf("%lld\n", ans);
}
return 0;
}