AtCoder Beginner Contest 128 F - Frog Jump

题意

有一只青蛙,有\(0, 1, \cdots, N - 1\)个荷叶。每个荷叶上有权值\(s_i\)。

  1. 选定\(A\), \(B\),初始分数为\(0\)。
    当前位置为\(x\):
  2. 对于\(y = x + A\):
    • 如果\(y = N - 1\),游戏结束。
    • 如果\(y \neq N - 1\),但是\(y\)这个荷叶存在,那么分数增加\(s_i\),并且这片荷叶消失。
    • 如果\(y \neq N - 1\),但是\(y\)这个荷叶不存在,那么分数减去\(10^{100}\),游戏结束。
  3. 对于\(y = x - B\):
    • 如果\(y = N - 1\),游戏结束。
    • 如果\(y \neq N - 1\),但是\(y\)这个荷叶存在,那么分数增加\(s_i\),并且这片荷叶消失。
    • 如果\(y \neq N - 1\),但是\(y\)这个荷叶不存在,那么分数减去\(10^{100}\),游戏结束。
      问选定最优的\(A\)、\(B\)的情况下,得到的最高分数为多少?

思路

我们考虑,选定了\(A\)、\(B\)后,青蛙的行走路线为:
\[
\begin{eqnarray*}
0, A, A - B, A + (A - B), 2(A - B), \cdots, K(A - B), A + K(A - B)
\end{eqnarray*}
\]
我们令\(C = A - B\):
\[
\begin{eqnarray*}
0, A, C, A + C, 2C, \cdots, KC, A + KC
\end{eqnarray*}
\]
显然有:\(A + KC = N - 1\):
\[
\begin{eqnarray*}
0, N - 1 - KC, C, N - 1 - (K - 1)C, 2C, \cdots, KC, N - 1
\end{eqnarray*}
\]
那么当\(K\)、\(C\)确定的时候,行走路线就已经确定。
并且有一个限制条件为\(KC < N\),那么显然枚举\(K\)、\(C\)是\(O(nlogn)\)的。
并且我们发现,当我们固定\(C\),递增\(K\)的时候,行走路线的变化是这样的:
\[
\begin{eqnarray*}
&&0, N - 1\&&0, N - 1 - C, C, N - 1\&&0, N - 1 - 2C, C, n - 1 - C, 2C, N - 1\\end{eqnarray*}
\]
每次增加的是\(N - 1 - KC\)和\(KC\),这两个点,只需要加上就好了,并且要注意判断是否走到重复的点上了。

代码

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define N 100010
int n;
ll s[N];
int used[N];

int main() {
    while (scanf("%d", &n) != EOF) {
        for (int i = 0; i < n; ++i) {
            scanf("%lld", s + i);
        }
        memset(used, 0, sizeof used);
        ll res = 0;
        for (int C = 1; C <= n; ++C) {
            ll tmp = 0;
            for (int k = 1; 1ll * k * C < n; ++k) {
                int a = k * C;
                int b = n - 1 - k * C;
                int A = b, B = b - C;
                if (A <= 0 || B <= 0) break;
                if (a < 0 || a >= n || b < 0 || b >= n || a == b) break;
                if (used[a] == C || used[b] == C) {
                    break;
                }
                used[a] = C;
                used[b] = C;
                tmp += s[a];
                tmp += s[b];
                res = max(res, tmp);
            }
        }
        printf("%lld\n", res);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Dup4/p/10929996.html

时间: 2024-08-30 02:45:52

AtCoder Beginner Contest 128 F - Frog Jump的相关文章

AtCoder Beginner Contest 152 - F - Tree and Constraints (容斥定理+树上路径的性质)

AtCoder Beginner Contest 152 - F - Tree and Constraints (容斥定理+树上路径的性质) We have a tree with NN vertices numbered 11 to NN. The ii-th edge in this tree connects Vertex aiai and Vertex bibi. Consider painting each of these edges white or black. There ar

AtCoder Beginner Contest 132 F - Small Products

数 sqrt 缩小范围 整除分块 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 1

AtCoder Beginner Contest 133 F - Colorful Tree

题意:给出一棵n个点的树,每条边有颜色和边长两个属性,n个询问,每次询问把颜色x的边的边长变为y问u到v的路径长度是多少,询问之间独立. 解法:这道题蛮有意思的.解法参考https://www.cnblogs.com/Tieechal/p/11185912.html这位大佬的,这里说下我的理解. 对于每组询问(x,y,u,v)答案比较显然就是dist(u,v)+(sumlen[x]-sumcnt[x]*y),但是这道题在线不好做我们考虑离线做.但是答案的式子是设计到两个点的,怎么才能离线做呢?这

AtCoder Beginner Contest 153 F - Silver Fox vs Monster

题目链接 https://atcoder.jp/contests/abc153/tasks/abc153_f 题意 : 在坐标轴上有一些怪兽,每个怪兽有对应的生命值hi,你可以对他们进行炮击,你的每次炮击可以队该点前后D范围内的怪兽造成A的伤害,问最少要炮击多少次. 我的最初的想法是先排序,扫到最左边的怪兽,先进行炮击,把他打死,然后记录炮击了多少次,然后把其后2d距离的怪兽都炮击一下发现超时 代码如下: inline ll read(){ ll s=0,w=1; char ch=getchar

AtCoder Beginner Contest 136

AtCoder Beginner Contest 136 Contest Duration : 2019-08-04(Sun) 20:00 ~ 2019-08-04(Sun) 21:40 Website: AtCoder BC-136 后面几题都挺考思考角度D. C - Build Stairs 题目描述: 有n座山从左到右排列,给定每一座山的高度\(Hi\),现在你可以对每座山进行如下操作至多一次:将这座山的高度降低1. 问是否有可能通过对一些山进行如上操作,使得最后从左至右,山的高度呈不下降

AtCoder Beginner Contest 154 题解

人生第一场 AtCoder,纪念一下 话说年后的 AtCoder 比赛怎么这么少啊(大雾 AtCoder Beginner Contest 154 题解 A - Remaining Balls We have A balls with the string S written on each of them and B balls with the string T written on each of them. From these balls, Takahashi chooses one

AtCoder Beginner Contest 155 简要题解

AtCoder Beginner Contest 155 A:签到失败,WA一次. int main() { int a, b, c; cin >> a >> b >> c; if(a == b && b == c) cout << "No"; else if(a == b || a == c || b == c) cout << "Yes"; else cout << &quo

【ATcoder】AtCoder Beginner Contest 161 题解

题目链接:AtCoder Beginner Contest 161 原版题解链接:传送门 A - ABC Swap 这题太水,直接模拟即可. 1 #include <iostream> 2 using namespace std; 3 int main() { 4 int a, b, c; 5 cin >> a >> b >> c; 6 swap(a, b); 7 swap(a, c); 8 cout << a << " &

AtCoder Beginner Contest 103 D(贪心)

AtCoder Beginner Contest 103 D 题目大意:n个点,除第n个点外第i与第i+1个点有一条边,给定m个a[i],b[i],求最少去掉几条边能使所有a[i],b[i]不相连. 按右端点从小到大排序,如果当前选的去掉的边在区间内,那么符合条件,否则ans++,并贪心地把去掉的边指向右端点,因为前面的区间都满足条件了,所以要去掉的边要尽量向右移使其满足更多的区间. 1 #include <iostream> 2 #include <cstdio> 3 #incl