Atcoder abc A~E

本文介绍了四道算法题目,涉及最优购买策略、模拟行走路径、矩阵循环检查以及寻找特定子序列。解法分别涉及条件判断、模拟过程、循环检查和双指针技巧,展示了算法在解决实际问题中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ABC 265 A~E

A

题意:你要买 n 个苹果,买 1 个要 x 元,买 3 个要 y 元,问最少要花多少钱

解法:判断 3*x 是否小于 y,然后输出

Code : 

# include <bits/stdc++.h>
//# include "windows.h"
# define ll long long
//# define int ll
# define db double
# define mod 998244353
//# define mod 1000000007
# define inf 1000000000
# define INF 1000000000000000000
# define fi first
# define se second
# define pb push_back
# define RI register int
# define vi vector <int>
# define REP(i, n, m) for (RI i = (n);i <= (m);i++)
# define rep(i, n) REP(i, 1, n)
# define foreach(i, c) for (__typeof__((c).end()) i = (c).begin();i != (c).end();i++)
# define pi acos(-1)
# define pii pair <int, int>
using namespace std;
int dx[15] = {0, 0, 1, -1, -1, -1, 1, 1};
int dy[15] = {1, -1, 0, 0, -1, 1, -1, 1};

int main(){
	int n, x, y;
	cin >> x >> y >> n;
	if (x*3 <= y) printf("%d", x*n);
	else printf("%d", (n/3) * y + (n%3) * x);
	return 0;
}

B

题意:有 n 个房间,从 i 到 i+1 个房间要 ​ t_i 秒,一开始你有 t 秒的时间,问你可不可以走到第 n 个房间,其中走到第 x_i 个房间可以增加 ​y_i 秒的时限

解法:模拟

Code: ​ ​

# include <bits/stdc++.h>
//# include "windows.h"
# define ll long long
# define int ll
# define db double
# define mod 998244353
//# define mod 1000000007
# define inf 1000000000
# define INF 1000000000000000000
# define fi first
# define se second
# define pb push_back
# define RI register int
# define vi vector <int>
# define REP(i, n, m) for (RI i = (n);i <= (m);i++)
# define rep(i, n) REP(i, 1, n)
# define foreach(i, c) for (__typeof__((c).end()) i = (c).begin();i != (c).end();i++)
# define pi acos(-1)
# define pii pair <int, int>
using namespace std;
int dx[15] = {0, 0, 1, -1, -1, -1, 1, 1};
int dy[15] = {1, -1, 0, 0, -1, 1, -1, 1};
​
int arr[200005], b[200005];
​
signed main(){
    int n, m, t;
    cin >> n >> m >> t;
    for (int i = 1;i < n;i++) scanf("%lld", &arr[i]);
    for (int i = 1;i <= m;i++){
        int x; scanf("%lld", &x);
        scanf("%lld", &b[x]);
    } t += b[1];
    for (int i = 1;i < n;i++){
        t -= arr[i];
        if (t <= 0){
            puts("No");
            return 0;
        }
        t += b[i+1];
    }
    puts("Yes");
    return 0;
}

C

题意:一个 n*m 的矩阵,每次可以往上下左右走,具体看 ​s_{i,j}  是什么,(D 是往下,U 是往上,L 是往左,R 是往右),不能走出边界,问最后停在那里,若可以循环走则输出 -1。

解法:模拟

Code:

# include <bits/stdc++.h>
//# include "windows.h"
# define ll long long
//# define int ll
# define db double
# define mod 998244353
//# define mod 1000000007
# define inf 1000000000
# define INF 1000000000000000000
# define fi first
# define se second
# define pb push_back
# define RI register int
# define vi vector <int>
# define REP(i, n, m) for (RI i = (n);i <= (m);i++)
# define rep(i, n) REP(i, 1, n)
# define foreach(i, c) for (__typeof__((c).end()) i = (c).begin();i != (c).end();i++)
# define pi acos(-1)
# define pii pair <int, int>
using namespace std;
int dx[15] = {0, 0, 1, -1, -1, -1, 1, 1};
int dy[15] = {1, -1, 0, 0, -1, 1, -1, 1};
​
int n, m, mp[505][505];
char s[505][505];
​
int main(){
    cin >> n >> m;
    rep(i, n) scanf("%s", s[i]+1);
    int x = 1, y = 1;
    while (1){
        if (mp[x][y]){
            puts("-1");
            return 0;
        }
        mp[x][y] = 1;
        char t = s[x][y];
        if (t == 'U'){
            if (x == 1){
                printf("%d %d", x, y);
                return 0;
            }
            x--;
        }
        if (t == 'D'){
            if (x == n){
                printf("%d %d", x, y);
                return 0;
            }
            x++;
        }
        if (t == 'L'){
            if (y == 1){
                printf("%d %d", x, y);
                return 0;
            }
            y--;
        }
        if (t == 'R'){
            if (y == m){
                printf("%d %d", x, y);
                return 0;
            }
            y++;
        }
    }
    return 0;
}
​
​

D

题意:给你一个长度为 n 的序列,问存不存在 x,y,z,w 满足\sum_{i=x}^{y-1} a_i= p\sum_{i-y}^{z-1}a_i = q\sum_{i=z}^{w-1} = r

解法1:先把所有和为 p 或 r 的区间,存到 vector 中,然后两层循环判断一下。

Code:

# include <bits/stdc++.h>
//# include "windows.h"
# define ll long long
# define int ll
# define db double
# define mod 998244353
//# define mod 1000000007
# define inf 1000000000
# define INF 1000000000000000000
# define fi first
# define se second
# define pb push_back
# define RI register int
# define vi vector <int>
# define REP(i, n, m) for (RI i = (n);i <= (m);i++)
# define rep(i, n) REP(i, 1, n)
# define foreach(i, c) for (__typeof__((c).end()) i = (c).begin();i != (c).end();i++)
# define pi acos(-1)
# define pii pair <int, int>
using namespace std;
int dx[15] = {0, 0, 1, -1, -1, -1, 1, 1};
int dy[15] = {1, -1, 0, 0, -1, 1, -1, 1};
​
int n, p, q, r, arr[200005], s[200005];
​
map <int, int> mp;
​
vector <pii> v1, v2;
​
signed main(){
    cin >> n >> p >> q >> r;
    for (int i = 1;i <= n;i++){
        scanf("%lld", &arr[i]);
        s[i] = s[i-1] + arr[i];
        if (s[i] == p) v1.pb({i, i});
        if (s[i] == r) v2.pb({i, i});
        if (mp[s[i]-p] != 0){
            v1.pb({mp[s[i]-p]+1, i});
        } 
        if (mp[s[i]-r] != 0){
            v2.pb({mp[s[i]-r]+1, i});
        }
        mp[s[i]] = i;
    }
    for (pii a : v1) for (pii b : v2){
        int num = s[b.fi-1] - s[a.se];
        if (num == q){
            puts("Yes");
            return 0;
        }
        if (num > q) break;
    }
    puts("No");
    return 0;
}
​
​

解法2:从 i 开始不断找区间和为 p,q 和 r的区间,最后输出就好了。

Code:

#include<bits/stdc++.h>
#define pii pair<int,int>
#define ll long long
#define F first
#define S second
using namespace std;
const int N=2e5+5;
ll n,p,q,r,a[N],sum[N];
int main(){
    scanf("%lld%lld%lld%lld",&n,&p,&q,&r);
    for(int i=1;i<=n;++i){
        scanf("%lld",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    for(int i=1;i<=n;++i){
        int y=lower_bound(sum+i,sum+n+1,sum[i-1]+p)-sum;
        int z=lower_bound(sum+y,sum+n+1,sum[y]+q)-sum;
        int w=lower_bound(sum+z,sum+n+1,sum[z]+r)-sum;
        if(sum[y]!=sum[i-1]+p || sum[z]!=sum[y]+q || sum[w]!=sum[z]+r){
            continue;
        }
        puts("Yes");
        return 0;
    }
    puts("No");
    return 0;
}
​

E

题意:n 次操作,一开始你在平面直角坐标系的原点上,每次你可以走到(x+a,y+b) 或(x+c,y+d)或​ (x+e,y+f),但是不能走到 ​(x_i,y_i)

解法:dp,具体看代码。(注:一定要写 unordered_map,否则会 TLE)

Code : 

# include <bits/stdc++.h>
# define ll long long
# define int ll
# define mod 998244353
# define fi first
# define se second
# define pii pair <int, int>
using namespace std;
​
int n, m, a, b, c, d, e, f, dp[305][305][305], ans = 0;
// 第 i 次操作中有 j 个操作 1,和 k 个操作 2 的方案数 
​
unordered_map <int, int> mp;
​
signed main(){
    scanf("%lld%lld%lld%lld%lld%lld%lld%lld", &n, &m, &a, &b, &c, &d, &e, &f);
    for (register int i = 1;i <= m;i++){
        int x, y; scanf("%lld%lld", &x, &y);
        mp[x*1e9+y] = 1;
    }
    dp[0][0][0] = 1;
    for (register int i = 1;i <= n;i++){
        for (register int j = 0;j <= i;j++){
            for (register int k = 0;k <= i-j;k++){
                int w = i-j-k;
                int x = j*a + k*c + w*e;
                int y = j*b + k*d + w*f;
                if (mp[x*1e9+y]) continue;
                if (j >= 1) dp[i][j][k] += dp[i-1][j-1][k];
                if (k >= 1) dp[i][j][k] += dp[i-1][j][k-1];
                if (i != j+k) dp[i][j][k] += dp[i-1][j][k];
                dp[i][j][k] %= mod;
            }
        }
    } 
    for (register int i = 0;i <= n;i++) for (register int j = 0;j <= n;j++) ans = (ans + dp[n][i][j]) % mod;
    printf("%lld", ans);
    return 0;
}
​
​

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值