首页 > 其他分享 >AtCoder Beginner Contest 362

AtCoder Beginner Contest 362

时间:2024-07-27 21:29:33浏览次数:14  
标签:AtCoder qu Beginner int yy ++ 362 dp dis

题目链接:AtCoder Beginner Contest 362

A. Buy a Pen

tag:签到

B. Right Triangle

tag:模拟

C. Right Triangle

tag:贪心

Description:给定\(n\)对整数\(l_i, r_i\);求一个整数序列,满足\(l_i <= x_i <= r_i\),且\(\sum_{i}^{n}x_i = 0\);如果没有则输出\(-1\)。

Solution:先判断是否有解,令\(mi = \sum_{i}^{n}l_i, ma = \sum_{i}^{n}r_i\)。如果\(mi <= 0 且 ma >= 0\)有解,否则无解。

  • 先假设所有值都取最小值,则\(sum = mi\),然后开始枚举当前位置的取值,看是否能令\(sum = 0\),否则当前值取最大值,继续向后枚举。

Competing:想到了如何判断是否有解,但是没想到贪心求解。

void solve(){
    cin >> n;
    int mi = 0, ma = 0;
    vector<pii> a(n);
    for (int i = 0; i < n; i ++){
        int l, r;
        cin >> l >> r;
        a[i] = {l, r};
        mi += l;
        ma += r;
    }
    if (mi > 0 || ma < 0){
        cout << "No\n";
    }
    else{
        cout << "Yes\n";
        for (int i = 0; i < n; i ++){  // 刚开始假设所有值都取最小值
            if (mi == 0){
                for (int j = i; j < n; j ++){
                    cout << a[j].fi << " ";
                }
                return;
            }
            mi -= a[i].fi;  // 开始选择第i个值
            if (a[i].fi <= -mi && -mi <= a[i].se){
                cout << -mi << " ";
                for (int j = i + 1; j < n; j ++){
                    cout << a[j].fi << " ";
                }
                return;
            }
            mi += a[i].se;
            cout << a[i].se << " ";      
        }
    }
}

D. Shortest Path 3

tag:Dijkstra

Description:给定一个图,每个点,边都有权值,求所有从起点\(1\)到\(i\)的路径长度(边的权值 + 点的权值)。

Solution:Dijkstra板子,将权值加上点的权值即可。

void solve(){
    cin >> n >> m;
    vector g(n + 5, vector<pii>());
    vector<int> dis(n + 5, 1e15), st(n + 5);
    vector<int> a(n + 5);
    for (int i = 1; i <= n; i ++)
        cin >> a[i];

    for (int i = 0; i < m; i ++){
        int x, y, w;
        cin >> x >> y >> w;
        g[x].eb(w, y);
        g[y].eb(w, x);
    }
    auto dijkstra = [&](int u) -> void{
        dis[u] = a[u];
        priority_queue<pii, vector<pii>, greater<pii>> qu;
        qu.ep(dis[u], u);
        
        while (qu.size()){
            auto [w, y] = qu.top();
            qu.pop();
            if (st[y])
                continue;
            
            st[y] = true;
            for (auto [ww, yy] : g[y]){
                if (a[yy] + ww + w < dis[yy]){
                    dis[yy] = ww + w + a[yy];
                    qu.ep(dis[yy], yy);
                }
            }
        }
    };

    dijkstra(1);
    for (int i = 2; i <= n; i ++){
        cout << dis[i] << " ";
    } 
}

E. Count Arithmetic Subsequences

tag: dp

Description:给定一个数组\(a\),求不同长度的等差数列的个数(\(1 <= len <= a.size()\))。a.size() <= 80

Solution:因为\(a\)的长度很小,所有我们可以考虑\(dp\)。

  • 状态表示:显然需要有长度和公差,然后需要一个位置。所有我们使用\(dp[i][j][k]\),表示终点为\(i\),长度为\(j\),公差为\(k\)的所有等差数列的集合。

  • 状态转移:\(dp[i][j][k] += dp[x][j - 1][k], x < i 且 a[k] - a[x] = k\)。

  • 初始化:初始化长度为\(2\)的所有答案;注意到公差的范围很大,我们使用\(map\)进行离散化。

int dp[100][100][6500];
map<int, int> d;

void solve(){
    cin >> n;
    vector<int> a(n);
    int cnt = 1;
    for (int i = 0; i < n; i ++)
        cin >> a[i];
    for (int i = 0; i < n; i ++)
        for (int j = 0; j < n; j ++){
            if (!d[a[i] - a[j]])
                d[a[i] - a[j]] = cnt ++;  // 离散化
        }

    for (int i = 0; i < n; i ++){
        for (int j = 0; j < i; j ++){
            dp[i][2][d[a[i] - a[j]]] ++;  // 初始化长度为2的
        }

        for (int j = 0; j < i; j ++)
            for (int k = 3; k <= i + 1; k ++){
                dp[i][k][d[a[i] - a[j]]] += dp[j][k - 1][d[a[i] - a[j]]];
                dp[i][k][d[a[i] - a[j]]] %= mod;
            }
    }
    for (int k = 1; k <= n; k++){
        if (k == 1){
            cout << n << " ";
            continue;
        }
        int ans = 0;
        for (int i = 0; i < n; i++){
            for (int j = 1; j <= cnt; j++){
                ans += dp[i][k][j];
                ans %= mod;
            }
        }
        cout << ans << ' ';
    }
}

标签:AtCoder,qu,Beginner,int,yy,++,362,dp,dis
From: https://www.cnblogs.com/Sakura17/p/18327505

相关文章

  • AtCoder Beginner Contest 363
    上周去玩了(逃A-PilingUp(abc363A)题目大意给定分数,问晋级还差多少分。分别到\(100,200,300\)分能晋级。解题思路找到第一个大于当前分数的,其差即为答案。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){io......
  • AtCoder Beginner Contest 360 题解(C-E)
    C-MoveIt题目链接:C-MoveIt题目大意:有\(N\)个盒子和\(N\)个物品编号为\(1-N\),物品\(i\)在盒子\(A_i\)中,重量为\(W_i\),你可以进行一种操作将盒子中的一件物品移动到其他任意盒子中,代价为\(W_i\),求使得所有盒子中只存在一件物品的最小操作代价。题解:贪心,可以发现......
  • [lnsyoj538/luoguP3628/APIO2010]特别行动队
    题意原题链接给定序列\(a\)和自定义二次函数\(f(x)=ax^2+bx+c(a<0)\),要求将\(a\)分为几段(不妨设为\(k\)段),使得\(\sum_{i=1}^{k}f(\sum_{j=l_i}^{r_i}a_j)\)的值最大,求最大的值sol设计状态转移方程。显然,\(dp_i\)可以由\(dp_j\)转移当且仅当\(j<i\),这表示......
  • [atcoder utpc2023_p] Priority Queue 3
    PriorityQueue3题意:有一个小根堆和\(1\)~\(n\)个数,以及一个操作序列,+表示\(push\),-表示\(pop\),\(pop\)有\(m\)次,问你有多少种插入顺序使得最后的pop集合与给出的的数字集合\(Y\)相同。首先有个浅显的发现:对于不在\(Y\)集合中的数,可选范围形如一个阶梯,换句话......
  • Solution - Atcoder Xmas2019E Sum of f(n)
    考虑\(F(n)=\sum\limits_{i=1}^nf_i=\sum\limits_{i=1}^n\sum\limits_{p\in\mathbb{P},k\ge1}[p^k|i]=\sum\limits_{p\in\mathbb{P},k\ge1}\lfloor\frac{n}{p^k}\rfloor\)。对于这个\(\lfloor\frac{n}{x}\rfloor\),一个比较经典的想法就是考虑对其......
  • Solution - Atcoder Xmas2019D Sum of (-1)^f(n).md
    对于\(f(i)=(-1)^{\sum\limits_jc_j}(i=\prod\limits_jp_j^{c_j}(p_j\in\mathbb{P}))\),一个比较特殊的值就是在\(i\in\mathbb{P}\)时有\(f(i)=-1\)。于是考虑PowerfulNumber筛,构造积性函数\(g\)使得对于\(i\in\mathbb{P}\)有\(g(p)=f(p)\)且\(g\)易......
  • AtCoder Beginner Contest 363
    AtCoderBeginnerContest363前言只出了三题,被d卡住了,事实上e题应该对我而言更简单,没及时换题。A-PilingUp(atcoder.jp)思路代码#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;intmain(){ios::sync_with_stdio(false);cin.......
  • AtCoder Beginner Contest 363
    AtCoderBeginnerContest363PilingUp模拟题。点击查看代码#include<bits/stdc++.h>usingnamespacestd;inta;signedmain(){cin>>a;if(a%100!=0){a%=100;cout<<100-a;}else{cout<<100;}retur......
  • SSM小说阅读网站-计算机毕业设计源码11362
    摘 要本文介绍了一个基于SSM框架和MySQL数据库的小说阅读网站的设计与实现。该网站旨在为用户提供一个方便、舒适的在线小说阅读平台。该小说阅读网站具有以下主要功能:用户注册与登录、小说分类浏览、小说搜索、阅读历史记录、小说畅听等。通过该网站,用户可以根据自己的兴......
  • AtCoder Beginner Contest 363
    AtCoderBeginnerContest363A-PilingUp每100分显示一个^。现在已知分数,问想要多显示一个^需要再得多少分。模拟题,显示\(i\)个^的最小分数是\(100\timesi\),而当前的^是\([\frac{R}{100}]\),\(R\)是当前的分数。所以答案就是\(([\frac{R}{100}]+1)\times100-R\)#includ......