竞赛地址
https://atcoder.jp/contests/arc135/tasks。
A - Floor, Ceil - Decomposition
https://atcoder.jp/contests/arc135/tasks/arc135_a。
题解
数学题。
给一个正整数
X
X
X,
f
(
x
)
f(x)
f(x) 是一通操作后乘积最大值。
假设
X
−
=
⌊
x
2
⌋
,
X
+
=
⌈
x
2
⌉
X_-=\lfloor \frac{x}{2} \rfloor,\ X_+=\lceil \frac{x}{2} \rceil
X−=⌊2x⌋, X+=⌈2x⌉。我们可以写出
f
(
1
)
=
1
f
(
X
)
=
m
a
x
(
X
,
f
(
X
−
)
×
f
(
X
+
)
)
∀
x
≥
2
f(1)=1\\ f(X)=max(X, f(X_-) \times f(X_+))\ \forall x \ge 2
f(1)=1f(X)=max(X,f(X−)×f(X+)) ∀x≥2。
下面我们来推导数学公式
f
(
X
−
)
×
f
(
X
+
)
≥
X
−
×
X
+
≥
X
−
1
2
×
X
2
≥
X
−
1
4
×
X
f(X_-) \times f(X_+) \ge X_- \times X_+ \ge \frac{X-1}{2} \times \frac{X}{2} \ge \frac{X-1}{4} \times X
f(X−)×f(X+)≥X−×X+≥2X−1×2X≥4X−1×X。
这样,我们知道当
X
≥
4
X \ge 4
X≥4 的时候,
X
−
1
4
×
X
≥
X
\frac{X-1}{4} \times X \ge X
4X−1×X≥X。
因此:
f
(
X
)
=
X
∀
X
≤
4
f
(
X
)
=
f
(
X
−
)
×
f
(
X
+
)
∀
X
≥
5
f(X)=X\ \forall X \leq 4\\ f(X)=f(X_-) \times f(X_+)\ \forall X \ge 5
f(X)=X ∀X≤4f(X)=f(X−)×f(X+) ∀X≥5。
这样,我们可以用 DFS 来实现。
下面我们来看一下数据范围,
1
≤
X
≤
1
0
18
1 \leq X \leq 10^{18}
1≤X≤1018,数据很大,需要使用记忆化搜索来优化。
AC 代码
#include<bits/stdc++.h>
using namespace std;
using LL=long long;
using PLL=pair<LL,LL>;
const LL MO=998244353;
unordered_map<LL, LL> M;
LL dfs(LL x) {
if (M.count(x)) {
return M[x];
}
M[x]=x;
if (x<=4) {
return M[x];
}
return M[x]=(dfs(x/2)*dfs((x+1)/2))%MO;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
LL x;
cin>>x;
cout<<dfs(x)<<"\n";
return 0;
}
B - Sum of Three Terms
https://atcoder.jp/contests/arc135/tasks/arc135_b。
题解
又是数学题。
假设序列
A
A
A 为满足条件的序列,这样
S
i
=
A
i
+
A
i
+
1
+
A
i
+
2
⇒
A
i
+
2
=
S
i
−
A
i
−
A
i
+
1
S_i = A_i+A_{i+1}+A_{i+2} \Rightarrow A_{i+2}=S_i-A_i-A_{i+1}
Si=Ai+Ai+1+Ai+2⇒Ai+2=Si−Ai−Ai+1。
当
i
=
1
i=1
i=1 的时候,
A
3
=
S
1
−
A
1
−
A
2
A_3=S_1-A_1-A_2
A3=S1−A1−A2,这个方程中有
3
3
3 个未知数,这样我们假设
A
1
=
a
,
A
2
=
b
A_1=a,\ A_2=b
A1=a, A2=b,我们可以推导出如下
{
A
1
=
a
A
2
=
b
A
3
=
S
1
−
A
1
−
A
2
=
S
1
−
a
−
b
A
4
=
S
2
−
A
2
−
A
3
=
S
2
−
S
1
+
a
A
5
=
S
3
−
A
3
−
A
4
=
S
3
−
S
2
+
b
A
6
=
S
4
−
A
4
−
A
5
=
S
4
−
S
3
−
a
−
b
A
7
=
S
5
−
A
4
−
A
6
=
S
5
−
S
4
+
a
A
8
=
S
6
−
A
6
−
A
7
=
S
6
−
S
5
+
b
.
.
.
\begin{cases} A_1=a \\ A_2=b \\ A_3=S_1-A_1-A_2=S_1-a-b \\ A_4=S_2-A_2-A_3=S_2-S_1+a \\ A_5=S_3-A_3-A_4=S_3-S_2+b \\ A_6=S_4-A_4-A_5=S_4-S_3-a-b\\ A_7=S_5-A_4-A_6=S_5-S_4+a \\ A_8=S_6-A_6-A_7=S_6-S5+b\\ ... \end{cases}
⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧A1=aA2=bA3=S1−A1−A2=S1−a−bA4=S2−A2−A3=S2−S1+aA5=S3−A3−A4=S3−S2+bA6=S4−A4−A5=S4−S3−a−bA7=S5−A4−A6=S5−S4+aA8=S6−A6−A7=S6−S5+b...
这样,我们就知道了规律。下面我们需要知道什么时候有解。
解的存在性,我们可以使用一个最简单的序列
S
1
,
S
2
,
S
3
S_1, S_2, S_3
S1,S2,S3 是否存在一对
(
a
,
b
)
(a,b)
(a,b) 满足,这样可得。
{
S
1
≤
a
S
2
≤
b
a
+
b
≤
S
3
\begin{cases} S_1 \leq a\\ S_2 \leq b\\ a+b \leq S_3 \end{cases}
⎩⎪⎨⎪⎧S1≤aS2≤ba+b≤S3
所以,
当
S
1
+
S
2
>
S
3
S_1+S_2>S_3
S1+S2>S3 时候,问题无解。
当
S
1
+
S
2
≤
S
3
,
(
a
,
b
)
=
(
S
1
,
S
2
)
S_1+S_2 \leq S_3,\ (a,b)=(S_1,S_2)
S1+S2≤S3, (a,b)=(S1,S2),存在解。
这样,本题就变成一个模拟题。
AC代码
#include<bits/stdc++.h>
using namespace std;
using LL=long long;
using PLL=pair<LL,LL>;
const int N=3e5+10;
LL s[N];
LL a[N];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
LL n;
cin>>n;
for (LL i=1; i<=n; i++) {
cin>>s[i];
}
LL sum=0;
LL c1=0;
for (LL i=1; i<n; i+=3) {
sum+=s[i]-s[i+1];
c1=max(c1, sum);
}
sum=0;
LL c2=0;
for (LL i=2; i<n; i+=3) {
sum+=s[i]-s[i+1];
c2=max(c2, sum);
}
sum=0;
LL c3=0;
for (LL i=3; i<n; i+=3) {
sum+=s[i]-s[i+1];
c3=max(c3, sum);
}
if (c1+c2+c3>s[1]) {
cout<<"No\n";
return 0;
}
a[1]=c1;a[2]=c2;a[3]=s[1]-c1-c2;
for (LL i=2; i<=n; i++) {
a[i+2]=s[i]-a[i]-a[i+1];
}
cout<<"Yes\n";
for (LL i=1; i<=n+2; i++) {
cout<<a[i]<<" ";
}
cout<<"\n";
return 0;
}