E
https://atcoder.jp/contests/abc230/tasks/abc230_e
先找出来
k
0
=
f
l
o
o
r
(
s
q
r
t
(
n
)
)
k0 = floor(sqrt(n))
k0=floor(sqrt(n))
可以发现
f
l
o
o
r
(
n
/
i
)
=
k
floor(n / i) = k
floor(n/i)=k
k
<
=
n
/
i
<
=
k
+
1
k <= n / i <= k + 1
k<=n/i<=k+1
n
/
(
k
+
1
)
<
=
i
<
=
n
/
k
n / (k + 1) <= i <= n / k
n/(k+1)<=i<=n/k
这样我们可以在找出来公式
#include <bits/stdc++.h>
using namespace std ;
int main()
{
long long n, sum, k ;
cin >> n ;
for (long long i = 1; i <= n; i ++ ) {
if (i * i <= n) k = i ;
else break ;
}
sum = 0 ;
for (long long i = 1 ; i <= k; i ++ )
sum += ((n / i) - (n / (i + 1))) * i ;
for (long long i = 1 ;i <= n / (k + 1); i ++ ) sum += (n / i) ;
cout << sum << endl ;
return 0 ;
}
F
dp
递推
给出的是一个长度为N的序列A,你可以做任何次数的操作:当序列的长度至少为2时,选择两个相邻的值,删除它们,并在它们原来的位置插入它们的和。有多少个序列可以从零或更多的操作中产生?对答案取998244353的模数。
#include <bits/stdc++.h>
using namespace std ;
const int N = 2e5 + 10 ;
const int mod = 998244353 ;
int n ;
long long a[N] ;
long long f[N] ;
unordered_map<long long, long long>mp ;
int main()
{
cin >> n >> a[1];
//线性dp
f[1] = 1 ;
for (int i = 2; i <= n; i ++ ) {
cin >> a[i] ;
//f[i] = f[i - 1] * 2 - 重复部分
f[i] = ((f[i - 1] << 1) - mp[a[1]] + mod) % mod ;
mp[a[1]] = f[i - 1] ;
a[1] += a[i] ;
}
cout << f[n] << endl ;
return 0 ;
}