2023 CSP-J 题解

CSP-J 2023年题解

小苹果

题目描述

小 Y 的桌子上放着 nnn 个苹果从左到右排成一列,编号为从 111nnn

小苞是小 Y 的好朋友,每天她都会从中拿走一些苹果。

每天在拿的时候,小苞都是从左侧第 111 个苹果开始、每隔 222 个苹果拿走 111 个苹果。随后小苞会将剩下的苹果按原先的顺序重新排成一列。

小苞想知道,多少天能拿完所有的苹果,而编号为 nnn 的苹果是在第几天被拿走的?

输入格式

输入的第一行包含一个正整数 nnn,表示苹果的总数。

输出格式

输出一行包含两个正整数,两个整数之间由一个空格隔开,分别表示小苞拿走所有苹果所需的天数以及拿走编号为 nnn 的苹果是在第几天。

输入输出样例 #1

输入 #1

8

输出 #1

5 5

说明/提示

【样例 111 解释】

小苞的桌上一共放了 888 个苹果。
小苞第一天拿走了编号为 111444777 的苹果。
小苞第二天拿走了编号为 222666 的苹果。
小苞第三天拿走了编号为 333 的苹果。
小苞第四天拿走了编号为 555 的苹果。
小苞第五天拿走了编号为 888 的苹果。

【样例 222

见选手目录下的 apple/apple2.in 与 apple/apple2.ans。

【数据范围】

对于所有测试数据有:1≤n≤1091\leq n\leq 10^91n109

测试点n≤n\leqn特殊性质
1∼21\sim 212101010
3∼53\sim 53510310^3103
6∼76\sim 76710610^6106
8∼98\sim 98910610^6106
10101010910^9109

特殊性质:小苞第一天就取走编号为 nnn 的苹果。

解题思路

每隔两个拿走一个,换一种说法,就是当 indexmod  3=1index \mod 3 = 1indexmod3=1 的时候,第 indexindexindex 个苹果会被拿走。

所以如果某一天只剩下了 mmm 个苹果,并且 mmod  3=1m \mod 3 = 1mmod3=1 的时候,第 nnn 个苹果就被拿走了。至于计算每天被拿走的苹果数量,我们用这个公式来计算。

num=⌈m/3⌉num = \lceil m / 3 \rceilnum=m/3

#include <bits/stdc++.h>

using namespace std;

int n, ans1, ans2;

int main()
{
    cin >> n;
    while (n)
    {
        ans1++;
        if (n % 3 == 1 && ans2 == 0) // 看看啥时候取最后一个
            ans2 = ans1; 
        n -= n / 3 + (int)(n % 3 != 0); // 记得向上取整
    }
    cout << ans1 << " " << ans2 << '\n';
    return 0;
}

因为每次大概要少 13\frac{1}{3}31 的苹果,所以时间复杂度就是 logloglog 级别。

公路

题目描述

小苞准备开着车沿着公路自驾。

公路上一共有 nnn 个站点,编号为从 111nnn。其中站点 iii 与站点 i+1i + 1i+1 的距离为 viv_ivi 公里。

公路上每个站点都可以加油,编号为 iii 的站点一升油的价格为 aia_iai 元,且每个站点只出售整数升的油。

小苞想从站点 111 开车到站点 nnn,一开始小苞在站点 111 且车的油箱是空的。已知车的油箱足够大,可以装下任意多的油,且每升油可以让车前进 ddd 公里。问小苞从站点 111 开到站点 nnn,至少要花多少钱加油?

输入格式

输入的第一行包含两个正整数 nnnddd,分别表示公路上站点的数量和车每升油可以前进的距离。

输入的第二行包含 n−1n - 1n1 个正整数 v1,v2…vn−1v_1, v_2\dots v_{n-1}v1,v2vn1,分别表示站点间的距离。

输入的第三行包含 nnn 个正整数 a1,a2…ana_1, a_2 \dots a_na1,a2an,分别表示在不同站点加油的价格。

输出格式

输出一行,仅包含一个正整数,表示从站点 111 开到站点 nnn,小苞至少要花多少钱加油。

输入输出样例 #1

输入 #1

5 4
10 10 10 10
9 8 9 6 5

输出 #1

79

说明/提示

【样例 1 解释】

最优方案下:小苞在站点 111 买了 333 升油,在站点 222 购买了 555 升油,在站点 444 购买了 222 升油。

【样例 2】

见选手目录下的 road/road2.in 与 road/road2.ans。

【数据范围】

对于所有测试数据保证:1≤n≤1051 \leq n \leq 10^51n1051≤d≤1051 \leq d \leq 10^51d1051≤vi≤1051 \leq v_i \leq 10^51vi1051≤ai≤1051 \leq a_i \leq 10^51ai105

测试点n≤n \leqn特殊性质
1∼51\sim 515888
6∼106\sim 1061010310^3103
11∼1311\sim 13111310510^5105A
14∼1614\sim 16141610510^5105B
17∼2017\sim 20172010510^5105
  • 特殊性质 A:站点 111 的油价最低。
  • 特殊性质 B:对于所有 1≤i<n1 \leq i < n1i<nviv_ividdd 的倍数。

解题思路

简单贪心题,我们从站点一运动到站点 nnn,车可以装任意多的油并且加油站里面的油也足够多,问最少花多少钱。

我们很简单就能想到,每次我们加油,只需要保证可以到达距离当前加油站最近,并且比当前加油站更便宜的其他加油站即可。

因为我们在当前加油站加油不如走到更便宜的加油站之后再加。

本题代码要比思路难搞。

#include <bits/stdc++.h>
#define int long long // 这里偷懒了,大家不要向我学习

using namespace std;

const int maxn = 1e5 + 5;
int n, d;
int v[maxn], a[maxn];

signed main()
{
    cin >> n >> d;
    for (int i = 2; i <= n; i++)
        cin >> v[i], v[i] += v[i - 1]; // 把 v 变成从起点走到某一个点的距离
    for (int i = 1; i <= n; i++)
        cin >> a[i]; 
    int ans = 0, res = 0; // 因为只能买整数单位油,所以有可能走到第 i 个加油站之后还能再往前走一走,这里的 res 记录的是多往前走的距离
    int pre = 1;
    for (int i = 2; i <= n; i++)
    {
        if (a[i] < a[pre]) // 发现了比上一个加油站更便宜的
        {
            int gas = (v[i] - v[pre] - res + d - 1) / d; // 走到当前加油站需要多少油,注意上取整
            ans += gas * a[pre]; // 买这些油需要多少钱
            res = gas * d + res - (v[i] - v[pre]);
            pre = i;
        }
    }
    if (pre != n) // 最后在第 pre 个加油站加油直接走到 n
    {
        int gas = (v[n] - v[pre] - res + d - 1) / d;
        ans += gas * a[pre];
        res = gas * d + res - (v[n] - v[pre]);
    }
    cout << ans << '\n';
    return 0;
}

一元二次方程

题目背景

众所周知,对一元二次方程 ax2+bx+c=0,(a≠0)ax ^ 2 + bx + c = 0, (a \neq 0)ax2+bx+c=0,(a=0),可以用以下方式求实数解:

  • 计算 Δ=b2−4ac\Delta = b ^ 2 - 4acΔ=b24ac,则:
    1. Δ<0\Delta < 0Δ<0,则该一元二次方程无实数解。
    2. 否则 Δ≥0\Delta \geq 0Δ0,此时该一元二次方程有两个实数解 x1,2=−b±Δ2ax _ {1, 2} = \frac{-b \pm \sqrt \Delta}{2a}x1,2=2ab±Δ

例如:

  • x2+x+1=0x ^ 2 + x + 1 = 0x2+x+1=0 无实数解,因为 Δ=12−4×1×1=−3<0\Delta = 1 ^ 2 - 4 \times 1 \times 1 = -3 < 0Δ=124×1×1=3<0
  • x2−2x+1=0x ^ 2 - 2x + 1 = 0x22x+1=0 有两相等实数解 x1,2=1x _ {1, 2} = 1x1,2=1
  • x2−3x+2=0x ^ 2 - 3x + 2 = 0x23x+2=0 有两互异实数解 x1=1,x2=2x _ 1 = 1, x _ 2 = 2x1=1,x2=2

在题面描述中 aaabbb 的最大公因数使用 gcd⁡(a,b)\gcd(a, b)gcd(a,b) 表示。例如 121212181818 的最大公因数是 666,即 gcd⁡(12,18)=6\gcd(12, 18) = 6gcd(12,18)=6

题目描述

现在给定一个一元二次方程的系数 a,b,ca, b, ca,b,c,其中 a,b,ca, b, ca,b,c 均为整数且 a≠0a \neq 0a=0。你需要判断一元二次方程 ax2+bx+c=0a x ^ 2 + bx + c = 0ax2+bx+c=0 是否有实数解,并按要求的格式输出。

在本题中输出有理数 vvv 时须遵循以下规则:

  • 由有理数的定义,存在唯一的两个整数 pppqqq,满足 q>0q > 0q>0gcd⁡(p,q)=1\gcd(p, q) = 1gcd(p,q)=1v=pqv = \frac pqv=qp

  • q=1q = 1q=1则输出 {p},否则输出 {p}/{q},其中 {n} 代表整数 nnn 的值;

  • 例如:

    • v=−0.5v = -0.5v=0.5 时,pppqqq 的值分别为 −1-11222,则应输出 -1/2
    • v=0v = 0v=0 时,pppqqq 的值分别为 000111,则应输出 0

对于方程的求解,分两种情况讨论:

  1. Δ=b2−4ac<0\Delta = b ^ 2 - 4ac < 0Δ=b24ac<0,则表明方程无实数解,此时你应当输出 NO

  2. 否则 Δ≥0\Delta \geq 0Δ0,此时方程有两解(可能相等),记其中较大者为 xxx,则:

    1. xxx 为有理数,则按有理数的格式输出 xxx

    2. 否则根据上文公式,xxx 可以被唯一表示为 x=q1+q2rx = q _ 1 + q _ 2 \sqrt rx=q1+q2r 的形式,其中:

      • q1,q2q _ 1, q _ 2q1,q2 为有理数,且 q2>0q _ 2 > 0q2>0

      • rrr 为正整数且 r>1r > 1r>1,且不存在正整数 d>1d > 1d>1 使 d2∣rd ^ 2 \mid rd2r(即 rrr 不应是 d2d ^ 2d2 的倍数);

    此时:

    1. q1≠0q _ 1 \neq 0q1=0,则按有理数的格式输出 q1q _ 1q1,并再输出一个加号 +
    2. 否则跳过这一步输出;

    随后:

    1. q2=1q _ 2 = 1q2=1,则输出 sqrt({r})
    2. 否则若 q2q _ 2q2 为整数,则输出 {q2}*sqrt({r})
    3. 否则若 q3=1q2q _ 3 = \frac 1{q _ 2}q3=q21 为整数,则输出 sqrt({r})/{q3}
    4. 否则可以证明存在唯一整数 c,dc, dc,d 满足 c,d>1,gcd⁡(c,d)=1c, d > 1, \gcd(c, d) = 1c,d>1,gcd(c,d)=1q2=cdq _ 2 = \frac cdq2=dc,此时输出 {c}*sqrt({r})/{d}

    上述表示中 {n} 代表整数 {n} 的值,详见样例。

    如果方程有实数解,则按要求的格式输出两个实数解中的较大者。否则若方程没有实数解,则输出 NO

输入格式

输入的第一行包含两个正整数 T,MT, MT,M,分别表示方程数和系数的绝对值上限。

接下来 TTT 行,每行包含三个整数 a,b,ca, b, ca,b,c

输出格式

输出 TTT 行,每行包含一个字符串,表示对应询问的答案,格式如题面所述。

每行输出的字符串中间不应包含任何空格

输入输出样例 #1

输入 #1

9 1000
1 -1 0
-1 -1 -1
1 -2 1
1 5 4
4 4 1
1 0 -432
1 -3 1
2 -4 1
1 7 1

输出 #1

1
NO
1
-1
-1/2
12*sqrt(3)
3/2+sqrt(5)/2
1+sqrt(2)/2
-7/2+3*sqrt(5)/2

说明/提示

【样例 #2】

见附件中的 uqe/uqe2.inuqe/uqe2.ans

【数据范围】

对于所有数据有:1≤T≤50001 \leq T \leq 50001T50001≤M≤1031 \leq M \leq 10 ^ 31M103∣a∣,∣b∣,∣c∣≤M|a|,|b|,|c| \leq Ma,b,cMa≠0a \neq 0a=0

测试点编号M≤M \leqM特殊性质 A特殊性质 B特殊性质 C
111111
222202020
33310310 ^ 3103
44410310 ^ 3103
55510310 ^ 3103
66610310 ^ 3103
7,87, 87,810310 ^ 3103
9,109, 109,1010310 ^ 3103

其中:

  • 特殊性质 A:保证 b=0b = 0b=0
  • 特殊性质 B:保证 c=0c = 0c=0
  • 特殊性质 C:如果方程有解,那么方程的两个解都是整数。

解题思路

纯纯的模拟题,做这种题的时候一定要理清思路,模块化你的代码,方便调试。

具体思路看下面代码:

#include <bits/stdc++.h>
#define int long long // 偷懒了

using namespace std;

int T, m;
int a, b, c;
int F; // F 判断左边输出了没

int delta(int a, int b, int c) // 计算 Δ
{
    return b * b - 4 * a * c;
}

int gcd(int x, int y) // 两个数字的最大公约数
{
    if (y == 0)
        return x;
    return gcd(y, x % y);
}

void left() // 计算 -b/2a
{
    int d = delta(a, b, c), p, q;
    p = -b;
    q = 2 * a;
    if ((int)sqrt(d) * (int)sqrt(d) == d) // 如果 Δ 可以被开方就直接加到 -b 里面
        if (a > 0)
            p += sqrt(d);
        else
            p -= sqrt(d);
    int f = 1; // 通过除号上下两部分判断整体的正负
    if (p < 0) f = -f;
    if (q < 0) f = -f;
    p = abs(p); // 取绝对值,方便输出
    q = abs(q);
    if (p == 0) // 左边是 0 不用输出
    {
        F = 1; // 标记一下
        return ;
    }
    if (p % q == 0) //可以被整除
        cout << f * p / q;
    else
    {
        int g = gcd(p, q); // 化简后输出
        cout << f * p / g << "/" << q / g;
    }
}

void right() // +/-sqrt(Δ)/2a
{
    int d = delta(a, b, c), f = 1; // 用 f 判断正负
    if ((int)sqrt(d) * (int)sqrt(d) == d) // 如果可以被开方,说明 left 函数已经计算过一次了,直接结束
    {
        if (F == 1) // 左边没输出,说明结果是 0
            cout << 0;
        return ;
    }
    if (a < 0) 
        f = -1;
    int k = 1, q = abs(2 * a);
    for (int i = 2; i <= sqrt(d); i++) // 尝试对 Δ 进行开方,把整数提出来
        while (d % (i * i) == 0)
        {
            k *= i;
            d /= i * i;
        }
   	// 我们要注意一点,题目让我们输出较大值,那么当 2a 是负数,sqrt(Δ) 前面也是负号,当 2a 是正数,sqrt(Δ) 前面就是 + 号,所以无论如何都该输出 "+"
    if (F == 0) // 左边如果输出了,那么我们用符号进行连接
        cout << "+";  
    int g = gcd(k, q); // 求最大公约数方便化简
    if (k != g)
        cout << k / g << "*"; // 整除
    cout << "sqrt(" << d << ")"; 
    if (q != g) // 看看 2a 是不是需要化简
        cout << "/" << q / g;
    return ;
}

signed main()
{
    cin >> T >> m;
    while (T--) // 多组数据
    {
        cin >> a >> b >> c;
        int d = delta(a, b, c);
        if (d < 0)
        {
            cout << "NO" << '\n';
            continue;
        }
        left();
        right();
        F = 0;
        cout << '\n';
    }
    return 0;
}

旅游巴士

题目描述

小 Z 打算在国庆假期期间搭乘旅游巴士去一处他向往已久的景点旅游。

旅游景点的地图共有 nnn 处地点,在这些地点之间连有 mmm 条道路。其中 111 号地点为景区入口,nnn 号地点为景区出口。我们把一天当中景区开门营业的时间记为 000 时刻,则从 000 时刻起,每间隔 kkk 单位时间便有一辆旅游巴士到达景区入口,同时有一辆旅游巴士从景区出口驶离景区。

所有道路均只能单向通行。对于每条道路,游客步行通过的用时均为恰好 111 单位时间。

小 Z 希望乘坐旅游巴士到达景区入口,并沿着自己选择的任意路径走到景区出口,再乘坐旅游巴士离开,这意味着他到达和离开景区的时间都必须是 kkk 的非负整数倍。由于节假日客流众多,小 Z 在旅游巴士离开景区前只想一直沿着景区道路移动,而不想在任何地点(包括景区入口和出口)或者道路上停留

出发前,小 Z 忽然得知:景区采取了限制客流的方法,对于每条道路均设置了一个
“开放时间”aia _ iai,游客只有不早于 aia _ iai 时刻才能通过这条道路。

请帮助小 Z 设计一个旅游方案,使得他乘坐旅游巴士离开景区的时间尽量地早。

输入格式

输入的第一行包含 3 个正整数 n,m,kn, m, kn,m,k,表示旅游景点的地点数、道路数,以及旅游巴士的发车间隔。

输入的接下来 mmm 行,每行包含 3 个非负整数 ui,vi,aiu _ i, v _ i, a_ iui,vi,ai,表示第 iii 条道路从地点 uiu _ iui 出发,到达地点 viv _ ivi,道路的“开放时间”为 aia _ iai

输出格式

输出一行,仅包含一个整数,表示小 Z 最早乘坐旅游巴士离开景区的时刻。如果不存在符合要求的旅游方案,输出 -1

输入输出样例 #1

输入 #1

5 5 3
1 2 0
2 5 1
1 3 0
3 4 3
4 5 1

输出 #1

6

说明/提示

【样例 #1 解释】

小 Z 可以在 333 时刻到达景区入口,沿 1→3→4→51 \to 3 \to 4 \to 51345 的顺序走到景区出口,并在 666 时刻离开。

【样例 #2】

见附件中的 bus/bus2.inbus/bus2.ans

【数据范围】

对于所有测试数据有:2≤n≤1042 \leq n \leq 10 ^ 42n1041≤m≤2×1041 \leq m \leq 2 \times 10 ^ 41m2×1041≤k≤1001 \leq k \leq 1001k1001≤ui,vi≤n1 \leq u _ i, v _ i \leq n1ui,vin0≤ai≤1060 \leq a _ i \leq 10 ^ 60ai106

测试点编号n≤n \leqnm≤m \leqmk≤k \leqk特殊性质
1∼21 \sim 212101010151515100100100ai=0a _ i = 0ai=0
3∼53 \sim 535101010151515100100100
6∼76 \sim 76710410 ^ 41042×1042 \times 10 ^ 42×104111ai=0a _ i = 0ai=0
8∼108 \sim 1081010410 ^ 41042×1042 \times 10 ^ 42×104111
11∼1311 \sim 13111310410 ^ 41042×1042 \times 10 ^ 42×104100100100ai=0a _ i = 0ai=0
14∼1514 \sim 15141510410 ^ 41042×1042 \times 10 ^ 42×104100100100ui≤viu _ i \leq v _ iuivi
16∼2016 \sim 20162010410 ^ 41042×1042 \times 10 ^ 42×104100100100

解题思路

动态规划 + 最短路,在我们建完这个有向图之后,我们需要考虑一下状态转移的问题。

当我们从一个点转移到另外一个点,然后发现因为开放时间的问题,我们没有办法进行移动的时候。我们可以将时间加上若干个 k,也就相当于我晚几个时间 k 进入景点,这样的话就合法了。

我们令 dp[i][j]dp[i][j]dp[i][j] 表示从起点出发到达 iii 号点,花费时间 %k\%k%k 等于 jjj 所需要花费的最小时间,那么我们要求的最终答案就是 dp[n][0]dp[n][0]dp[n][0]

我们可以用类似于 dijkstra 的操作(spfa应该也行)来进行状态转移。

#include <bits/stdc++.h>
#define int long long // 偷懒了
#define INF 1000000000000000000 // 极大值

using namespace std;

const int maxn = 1e4 + 5;
int n, m, k, dis[maxn][105], head[maxn], tot;
bool vis[maxn][105]; 

struct edge{
    int nxt, to, w;
}e[maxn << 1];

void addedge(int u, int v, int w) // 链式前向星建边
{
    e[++tot].nxt = head[u];
    e[tot].to = v;
    e[tot].w = w;
    head[u] = tot;
}

int Ceil(int a, int b) // 把 a 加到恰好比 b 大
{
    return a + (b - a + k - 1) / k * k;
}

void dijkstra()
{
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
    for (int i = 1; i <= n; i++) // 初始化成极大值
        for (int j = 0; j <= 100; j++)
            dis[i][j] = INF;
    dis[1][0] = 0; // 起点达到的时间肯定是 0
    q.push(make_pair(0, 1)); 
    while (!q.empty())
    {
        int u = q.top().second, p = q.top().first;
        q.pop();
        if (vis[u][p % k] == 1)
            continue;
        vis[u][p % k] = 1;
        for (int i = head[u]; i; i = e[i].nxt)
        {
            int v = e[i].to, w = e[i].w;
            if (p >= w) // 这条边可以过
            {
                if (dis[v][(p + 1) % k] > p + 1) // 当前这个走法可以更新状态
                {
                    dis[v][(p + 1) % k] = p + 1; // 更新一下
                    q.push(make_pair(p + 1, v));
                }
            }
            else // 过不了
            {
                int ti = Ceil(p, w); // 加若干个 k 使得自己可以通过
                if (dis[v][(p + 1) % k] > ti + 1)
                {
                    dis[v][(p + 1) % k] = ti + 1; // 更新
                    q.push(make_pair(ti + 1, v));
                }
            }
        }
    }
}

signed main() 
{
    cin >> n >> m >> k;
    for (int i = 1; i <= m; i++) // 建边
    {
        int u, v, w;
        cin >> u >> v >> w;
        addedge(u, v, w);
    }
    dijkstra();
    if (dis[n][0] == INF) // 到达不了
        cout << -1;
    else    
        cout << dis[n][0]; // 否则输出答案
    return 0;
}
以下是几种不同实现的 2023CSP - J 复赛中某一题(推测是关于苹果拿取问题)的题解代码分析: ### 第一种实现 ```cpp #include<bits/stdc++.h> using namespace std; int n, day, ans; int main(){ cin >> n; int m = n; // 当前苹果数量 while(m) { // n 号苹果在每一轮都是最后一个苹果,也就是第 m 个苹果 day++; if(m%3==1 && !ans) ans = day; // n 号个苹果在这一天被拿走 m -= (m+3-1)/3; // 向上取整 } cout << day << ' ' << ans; return 0; } ``` 此代码中,定义了变量 `n` 表示苹果总数,`day` 统计天数,`ans` 记录 `n` 号苹果被拿走的天数。通过 `while` 循环模拟拿苹果过程,只要还有苹果就继续循环。每一轮增加一天,当当前苹果数 `m` 满足 `m%3==1` 且 `ans` 为 0 时,记录 `n` 号苹果被拿走的天数。每次拿完苹果后,苹果数 `m` 减去 `(m + 3 - 1) / 3`,实现向上取整计算拿走的苹果数。最后输出总天数 `day` 和 `n` 号苹果被拿走的天数 `ans` [^1]。 ### 第二种实现 ```cpp #include<bits/stdc++.h> using namespace std; int n; int main(){ int i,j; int d=0,t; int f=0; cin>>n; j=n; while(j-1>=0){ d++; if(j%3==1&&f==0){ t=d; f=1; } if(j%3==0){ j=j-j/3; } else{ j=j-j/3-1; } } cout<<d<<" "<<t; return 0; } ``` 该代码同样是解决苹果拿取问题。定义变量 `n` 为苹果总数,`d` 统计天数,`t` 记录 `n` 号苹果被拿走的天数,`f` 作为标记。通过 `while` 循环模拟拿苹果,每一轮天数 `d` 加 1。当 `j%3==1` 且 `f` 为 0 时,记录 `n` 号苹果被拿走的天数到 `t` 并将 `f` 置为 1。根据 `j` 是否能被 3 整除,分别计算拿完苹果后剩余的苹果数。最后输出总天数 `d` 和 `n` 号苹果被拿走的天数 `t` [^2]。 ### 第三种实现 ```cpp #include<iostream> using namespace std; int n,flag,pick_end; long long ans; int main() { cin>>n; while(n) { //每次拿t个 ans++; int t=1+(n-1)/3; if((n-1)%3==0 && pick_end==0) { pick_end=ans; } n-=t; } cout<<ans<<' '<<pick_end; return 0; } ``` 此代码中,`n` 为苹果总数,`ans` 统计天数,`pick_end` 记录 `n` 号苹果被拿走的天数。在 `while` 循环中,每一轮天数 `ans` 加 1,计算每次拿走的苹果数 `t` 为 `1 + (n - 1) / 3`。当 `(n - 1) % 3 == 0` 且 `pick_end` 为 0 时,记录 `n` 号苹果被拿走的天数。每轮结束后,苹果数 `n` 减去拿走的苹果数 `t`。最后输出总天数 `ans` 和 `n` 号苹果被拿走的天数 `pick_end` [^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值