Codeforces Round 931 (Div. 2)ABC

A. Too Min Too Max

题面:

给定由 n 个元素组成的数组 a,求表达式的最大值:
∣ a i − a j ∣ + ∣ a j − a k ∣ + ∣ a k − a l ∣ + ∣ a l − a i ∣ |a_i - a_j| + |a_j - a_k| + |a_k - a_l| + |a_l - a_i| aiaj+ajak+akal+alai
其中, ijkl 是数组 a 的四个不同的索引,其中 1 ≤ i , j , k , l ≤ n 1 \le i, j, k, l \le n 1i,j,k,ln

这里的 |x| 表示 x 绝对值。

思路:因为n的数据范围是>=4,所以直接升序排序然后进行操作就行了。以|最大-最小| + |最小-次大| + |次大 -次小| + |次小-最大|

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
const int N=1e6+10;
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;  
typedef pair<int,int> PII;
#define int long long

void solve()
{
    int n;    cin >> n;
    int a[N];
    for(int i=1;i<=n;i++)    cin >> a[i];
    sort(a+1,a+n+1);
    
    cout << abs(a[n]-a[1])+abs(a[1]-a[n-1])+abs(a[n-1]-a[2])+abs(a[2]-a[n]) << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T=1;
    cin >> T;
    while(T--)
        solve();
}

B. Yet Another Coin Problem

题面:

你有 5 种不同的硬币,每种硬币的价值都等于前 5 个三角形数字中的一个:1361015 。这些硬币种类非常多。你的目标

找出所需的最少数量的这些硬币,使它们的总价值相加正好是 n

我们可以证明答案总是存在的。

思路:数据范围很大,不可能说直接预处理一遍,然后直接输出值。很好的就会发现很大很大的数的时候,我们每次-15才是最优的方法。但是到了1-30的区间的时候,并不能这么做,例如23=17+6+1+1一共四次,但是我只要23=10+10+3一共三次就可以了。

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
const int N=1e6+10;
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;  
typedef pair<int,int> PII;
#define int long long

int a[100];
void solve()
{
    int n;    cin >> n;
    int ans=n;
    ans=min(ans,n/15+a[n%15]);
    ans=min(ans,n/10+a[n%10]);
    ans=min(ans,n/6+a[n%6]);
    ans=min(ans,n/3+a[n%3]);
    
    int k=(n-15)/15*15;
    int m=n-k;
    ans=min(ans,k/15+a[m]);
    
    cout << ans << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    for(int i=1;i<=30;i++)    a[i]=100;
    a[1]=1;    a[3]=1;        a[6]=1;
    a[10]=1;    a[15]=1;
    for(int i=1;i<=30;i++)
    {
        if(i>1)
            a[i]=min(a[i],a[i-1]+1);
        if(i>3)
            a[i]=min(a[i],a[i-3]+1);
        if(i>6)
            a[i]=min(a[i],a[i-6]+1);
        if(i>10)
            a[i]=min(a[i],a[i-10]+1);
    }
    
    int T=1;
    cin >> T;
    while(T--)
        solve();
}

C. Find a Mine

这是一个互动问题

给你一个行数为 n 列数为 m 的网格。坐标 (x,y) 代表网格上的单元格,其中 x( 1 ≤ x ≤ n 1≤x≤n 1xn) 是从上往下数的行号,y( 1 ≤ y ≤ m 1≤y≤m 1ym) 是从左往右数的列号。( 1 ≤ y ≤ m 1≤y≤m 1ym)是从左数起的列数。网格中保证有 2 颗地雷位于 两个不同的 单元,分别表示为 (x1,y1)(x2,y2)。允许向交互器提出的查询次数不超过 4 次,在这些查询之后,您需要提供其中 一个地雷 的位置。

在每次查询中,您可以选择任意网格单元 (x,y),作为回报,您将得到从两个地雷到所选单元的最小曼哈顿距离,即您将得到值
m i n ( ∣ x − x 1 ∣ + ∣ y − y 1 ∣ , ∣ x − x 2 ∣ + ∣ y − y 2 ∣ ) min(|x−x1|+|y−y1|,|x−x2|+|y−y2|) min(xx1∣+yy1∣,xx2∣+yy2∣)
您的任务是在进行查询后确定其中一个地雷的位置。

思路:

你可以直接问三个顶点,然后得到一个三个值,问(1,1)、(1,m)、(n,1),然后你根据(1,1)、(1,m)和1,1)、(n,1)这两个组合找到两个点,这两个点必有一个点是雷,你算出来一个点后,直接问一个是不是这个点,如果得到的值是0,那么就是这个点,直接输出就好了,否则就是另外一个点。

当然求点的代码,我就不说了,这个要是不会,真的得加训了。

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
const int N=1e6+10;
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
typedef long long ll;
typedef unsigned long long ull;  
typedef pair<int,int> PII;
#define int long long

void solve()
{
    int a[10];    memset(a,0,sizeof(a));
    int n,m;    cin >> n >> m;
    cout << "? 1 1" << endl;    fflush(stdout);
    cin >> a[1];

    cout << "? " << n << " " << 1 << endl;    fflush(stdout);
    cin >> a[2];
    
    cout << "? 1 " << m << endl;    fflush(stdout);
    cin >> a[3];
    
    int k1=a[1]+a[2];
    if(k1>=n-1&&(k1-(n-1))%2==0)
    {
        int j=(k1-(n-1))/2;
        int i=a[1]-j;
        cout << "? " << i+1 << " " << j+1 << endl;
        fflush(stdout);
        int x;    cin >> x;
        if(x==0)
        {
            cout << "! " << i+1 << " " << j+1 << endl;
                    fflush(stdout);
            return ;
        }
    }
    
    int k2=a[1]+a[3];
    if(k2>=m-1&&(k2-(m-1))%2==0)
    {
        int j=(k2-(m-1))/2;
        int i=a[1]-j;
        cout << "! " << j+1 << " " << i+1 << endl;
        fflush(stdout);
        return ;
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T=1;
    cin >> T;
    while(T--)
        solve();
}
  • 39
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值