首页 > 其他分享 >【23.05.03】好题题解

【23.05.03】好题题解

时间:2023-05-03 18:44:06浏览次数:43  
标签:CI int 题解 好题 leq maxn 23.05 dp define

好题题解

A

题目大意:

计算一个项数为 \(n\) 的多项式除以 \(x^3-x\) 的余数多项式。

数据范围:

对于 \(100\%\) 的数据:

  • \(2 \leq n \leq 2 \times 10 ^ 5\)

解题分析:

水题,直接多项式除法模拟即可。

需要注意细节。

AC Code:

# include <bits/stdc++.h>
using namespace std;
 
# define int long long
# define f(i,a,b) for(int i = a; i <= b; i ++)
# define g(i,b,a) for(int i = b; i >= a; i --)
# define CI const int
 
CI maxn = 2e5 + 7;
 
int n;
int a[maxn];
 
signed main(){
    freopen("remainder.in", "r", stdin);
    freopen("remainder.out", "w", stdout);
    cin >> n;
    f (i, 1, n + 1)
        scanf("%lld", &a[i]);
    g (i, n + 1, 4){
        a[i - 2] += a[i];
        a[i] = 0;
    }
    int m = 1;
    f (i, 1, n + 1)
        if (a[i])
            m = i;
    printf("%lld\n", m - 1);
    f (i, 1, m)
        printf("%lld ", a[i]);
    return 0;
}

B

题目大意:

有一个 \(n * n\) 的网格,每个网格有一个数 \(a_{i,j}\),每走一步可以走到相邻的格子,走到 \((i,j)\) 需要耗费 \(a_{i,j}\) 的体力,体力 \(<= 0\) 就嘎了。若刚开始有 \(v\) 点体力,从 \(x_1, y_1\) 出发,问在不嘎的情况下,最少需要多少步,可以走到 \(x_2, y_2\)。如果走不到,输出 NO

数据范围:

对于 \(100\%\) 的数据:

  • \(1 \leq n \leq 100\)
  • \(0 \leq a_{i,j} \leq 9\)
  • \(0 \leq v \leq 10000\)

解法分析:

注意到数据范围很小,可以考虑 \(dp\)。

设 \(dp_{i,j,k}\) 表示走 \(i\) 步到达 \((j,k)\) 时的最大体力值。那么,\(dp_{i,j,k} = \min{\{dp_{i-1,u,v} - a_{j,k}\}}\)。

需要注意的是,第一维需要开滚动数组优化。

AC Code:

# include <bits/stdc++.h>
using namespace std;
 
# define int long long
# define f(i,a,b) for(int i = a; i <= b; i ++)
# define g(i,b,a) for(int i = b; i >= a; i --)
# define CI const int
 
CI maxn = 107;
CI maxm = 5507;
CI dx[] = {0, 1, 0, -1};
CI dy[] = {1, 0, -1, 0};
 
int n, v;
int stx, sty, edx, edy;
int a[maxn][maxn];
int dp[2][maxn][maxn];
 
signed main(){
    freopen("desert.in", "r", stdin);
    freopen("desert.out", "w", stdout);
    cin >> n >> v >> sty >> stx >> edy >> edx;
    f (i, 1, n)
        f (j, 1, n)
            scanf("%lld", &a[i][j]);
    f (j, 0, n)
        f (k, 0, n)
            dp[0][j][k] = -2e18;
    dp[0][stx][sty] = v;
    f (i, 1, n * n){
        f (j, 1, n){
            f (k, 1, n){
                dp[i % 2][j][k] = -2e18;
                f (l, 0, 3){
                    int nx = j + dx[l];
                    int ny = k + dy[l];
                    if (nx >= 1 && nx <= n && ny >= 1 && ny <= n)
                        dp[i % 2][j][k] = max(dp[(i - 1) % 2][nx][ny] - a[j][k], dp[i % 2][j][k]);
                }
                // if (dp[i][j][k] == -2e18) printf("-inf ");
                // else printf("%lld ", dp[i][j][k]);
            }
            // printf("\n");
        }
        if (dp[i % 2][edx][edy] > 0){
            printf("%lld\n", i);
            // system("pause");
            return 0;
        }
        // printf("\n");
    }
    printf("-1\n");
    // system("pause");
    return 0;
}

C

题目大意:

给定一个长度为 \(n\) 的仅包含 \(\{-1,0,1\}\) 的序列,你可以做任意多次如下操作:

选择一个 \(2 \leq i \leq n\),执行 \(a_i += a_{i-1}\)。

你的目标是将序列优化为单调不降的,你想知道最少要做多少次操作。

数据范围:

对于 \(100\%\) 的数据:

  • \(1 \leq n \leq 10^6\)

解法分析:

一道线性 \(dp\) 好题。

设 \(dp_{i,j=-1/0/1}\) 表示第 \(i\) 位要变成 \(j\) 且前 \(i\) 项单调不降的最少操作次数。则只需根据变大/变小/不变三种情况分类讨论即可。

注意:第二维的 \(-1/0/1\) 可以改成 \(0/1/2\)。

AC Code:

# include <bits/stdc++.h>
using namespace std;
  
# define int long long
# define f(i,a,b) for(int i = a; i <= b; i ++)
# define g(i,b,a) for(int i = b; i >= a; i --)
# define CI const int
  
CI maxn = 1e6 + 7;
  
int n;
int a[maxn];
int dp[maxn][3];
  
signed main(){
    freopen("optimize.in", "r", stdin);
    freopen("optimize.out", "w", stdout);
    cin >> n;
    f (i, 1, n) scanf("%lld", &a[i]);
    f (i, 1, n)
        f (j, 0, 2)
            dp[i][j] = 2e18;
    dp[1][a[1] + 1] = 0;
    f (i, 2, n){
        f (j, -1, 1){
            if (a[i] == j){
                f (k, -1, j)
                    dp[i][j + 1] = min(dp[i][j + 1], dp[i - 1][k + 1]);
            }
            else if (a[i] > j)
                dp[i][j + 1] = min(dp[i][j + 1], dp[i - 1][0] + (a[i] - j));
            else if (j == 1)
                dp[i][j + 1] = min(dp[i][j + 1], dp[i - 1][2] + (j - a[i]));
        }
    }
    int ans = min(dp[n][0], min(dp[n][1], dp[n][2]));
    if (ans >= 2e18) printf("NO");
    else printf("%lld", ans);
    // system("pause");
    return 0;
}

还没写完呢,还有 Atcoder 的题没写呢。

吃饭去了,尽请期待。

标签:CI,int,题解,好题,leq,maxn,23.05,dp,define
From: https://www.cnblogs.com/yh2021shx/p/17369510.html

相关文章

  • 【题解】ABC300 F,G
    F.MoreHolidays题目分析:考虑刻画一下我们选择是什么样子的。考虑我们最后选择的\(T\)中的一段一定是形如:一个完整的S选择一个后缀\(+\)若干个完整的S\(+\)一个完整的S的前缀。这样的话就启示我们直接枚举这个前后缀选择的是什么,然后就可以很快算出来了,但是枚举前......
  • [POI2005]SAM-Toy Cars 题解(贪心+堆)
    题面首先考虑一个贪心策略:当地板已经放满需要取出一个时,取下一次使用时间\(nxt\)最晚的那个。所以我们只需要一个可以快速求出一个集合中\(nxt\)最小的点并删除,插入新点的数据结构,这里很容易想到堆。代码很简洁,注意数组的下标是位置还是颜色(考场100pts到0pts)。code:......
  • Valhalla Siege 题解
    题目传送门一道二分题。先观察数据范围,\(1\len,q\le200,000\),显然需要\(O(n\logn)\)的复杂度。且\(1\lek_i\le10^{14}\),需要开longlong。我们需要二分到第一个血量大于伤害值的武士的位置,前面的武士都死了。而在C++算法库中,有一个函数upper_bound(底层原理是二分)正......
  • [蓝桥杯 2017 国 C] 合根植物 题解
    题目传送门一道并查集模板题。没什么好说的,先给个并查集模板,神犇可以直接跳过。查找根:intfind_root(intn){if(fa[n]==n)returnn;returnfa[n]=find_root(fa[n]);}合并:voidmerge(intx,inty){intsx=find_root(x),sy=find_root(y);......
  • Cashier 题解
    题目传送门一道贪心题。我们可以记录每一位客人离开的时间,当下一位客人来临时,他们之间空闲的时间就是我们休息的时间。for(inti=1;i<=n;i++){intt,l;cin>>t>>l;ans+=(t-endt)/a;endt=t+l;}最后再加上所有客人都走后的空闲时间......
  • [ABC213D] Takahashi Tour 题解
    题目传送门一道dfs序题。题目中高桥每次只会去最小的那个点,所以要先对整张图进行排序。for(inti=1;i<=n;i++)sort(g[i].begin(),g[i].end());然后考虑dfs。高桥不会走重复的点,所以我们可以开一个vis数组进行标记。然后我们需要处理高桥君如果无路可走会返回上......
  • Codeforces Round 869 (Div. 2) A-D题解
    比赛地址A.Politics题意:有n个人对m个决案进行投票,对于每一个决案如果票数相同则所有人都离场,反之票数少的一方离场,现在提前知道了每个人的意见,让一些人参与投票,在保证第一个人不离场的情况下最终剩余人数最多是多少Solution把和第一个意见不同的给去掉就行了voidsolve(){......
  • AT_abc106_d [ABC106D] AtCoder Express 2 题解
    题目传送门解题思路区间\(dp\)。划分阶段:以左右城市之间的列车数量为阶段。状态表达:设\(f_{i,j}\)为城市\(i\)与城市\(j\)之间的列车数量。状态转移:由图可知,城市\(l\)与城市\(r\)之间的列车数量,就是城市\(l\)与城市\(r-1\)之间的列车数量与城市\(l+1\)与......
  • CF1817C Similar Polynomials 题解
    可能更好的阅读体验题目传送门Div.1C拉格朗日差值,赛时开香槟。题目大意给定\(d\)次两个多项式\(A(x),B(x)\)。求\(s\),使得\(B(x)\equivA(x+s)\pmod{10^9+7}\),保证\(s\)存在。给出多项式的形式为给出\(x=0,1,\cdots,d\)模\(10^9+7\)的值。\(d\le2.5\times......
  • CF三月D题题解
    cf1798d题意:重排序列,使得其中连续子序列和的绝对值最大的最大值小于序列最大值减最小值,序列和为0考虑这样一种构造方案:正负数分类,0直接不管然后记录当前和sum,当sum非负时,加上一个负数,当sum是负数时,加上一个正数即可正确性证明:显然前缀和都是合法的。考虑计算前缀和数组,满足......