2019 East Central North America 部分题解

题目链接:点这里

A.Retribution!

  • 题意
    给出 n n n个人的位置、 m m m个仓库1的位置以及 p p p个仓库2的位置。给每个人分配一个仓库 1 1 1和仓库 2 2 2,问这所有的最小距离总和。

  • 解题思路
    这道题题意非常明显,也告诉了我们贪心求解,由于他们的位置都是固定的,所以我们就相当于是一个分配问题,那么我们其实把每个人距离各个仓库的距离给求出来再排序取最小即可。 要注意仓库只能分配给一个人,一个人只能分配一个仓库。所以我们需要开vis数组进行标记。

  • AC代码

/**
  *@filename:A
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-23 11:24
**/
#include <bits/stdc++.h>
#define x first
#define y second

using namespace std;

typedef long long ll;
typedef pair<double,double> pdd;
const int N = 1000 + 5;
const int P = 1e9+7;

int n,m,p;
pdd judge[N],tar[N],feather[N];
bool visJudge1[N],visTar[N],visJudge2[N],visFeather[N];
struct node{
    int u,v;
    double dist;
    bool operator < (const node & A){
        if(dist == A.dist){
            return u < A.u;
        }
        return dist < A.dist;
    }
}ans1[N * N],ans2[N * N];
double getDist(pdd a,pdd b){
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
void solve(){
    int cnt1 = 0,cnt2 = 0;
    for(int i = 1; i <= n; ++ i){
        for(int j = 1; j <= m; ++ j){
            ans1[++cnt1].u = i;
            ans1[cnt1].v = j;
            ans1[cnt1].dist = getDist(judge[i],tar[j]);
        }
    }
    for(int i = 1; i <= n; ++ i){
        for(int j = 1; j <= p; ++ j){
            ans2[++cnt2].u = i;
            ans2[cnt2].v = j;
            ans2[cnt2].dist = getDist(judge[i],feather[j]);
        }
    }
    sort(ans1 + 1, ans1 + 1 + cnt1);
    sort(ans2 + 1, ans2 + 1 + cnt2);
    double sum = 0;
    for(int i = 1; i <= cnt1; ++ i){
        if(!visJudge1[ans1[i].u] && !visTar[ans1[i].v]){
            sum += ans1[i].dist;
            //cout << sum << endl;
            visJudge1[ans1[i].u] = true;
            visTar[ans1[i].v] = true;
        }
    }
    for(int i = 1; i <= cnt2; ++ i){
        if(!visJudge2[ans2[i].u] && !visFeather[ans2[i].v]){
            sum += ans2[i].dist;
            //cout << sum << endl;
            visJudge2[ans2[i].u] = true;
            visFeather[ans2[i].v] = true;
        }
    }
    printf("%.8lf\n",sum);
}
int main(){
    scanf("%d%d%d", &n, &m, &p);
    for(int i = 1; i <= n; ++ i){
        scanf("%lf%lf", &judge[i].x, &judge[i].y);
    }
    for(int i = 1; i <= m; ++ i){
        scanf("%lf%lf", &tar[i].x, &tar[i].y);
    }
    for(int i = 1; i <= p; ++ i){
        scanf("%lf%lf", &feather[i].x, &feather[i].y);
    }
    solve();
    return 0;
}

F.Musical Chairs

  • 题意
    相当于约瑟夫环。只不过 k k k不是固定的。对于每个人都有一个相应的 k k k值,其每个人编号从 1 1 1开始。在游戏的开始时,从第一个人开始计数,当某个人记到第一个人的 k k k时,该人出队,紧接这下个人开始从 1 1 1计数,而 k k k值则为第一个人计数的 k k k值。知道队里只剩一个人。

  • 解题思路
    由于 k k k是变化的,所以我们不能直接用公式,只能模拟。由于最后要输出编号,所以我们可以先用pair对存储其 k k k值和对应的编号。最后开始模拟,一定要注意模拟的细节,出队我们直接用数组覆盖即可。复杂度为 O ( n 2 ) O( n ^2) O(n2),可以通过。

  • AC代码

/**
  *@filename:F
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-23 10:03
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 10000 + 5;
const int P = 1e9+7;

int n;
pair<int,int> a[N];
void solve(){
    int pos = 0;//当前所在的下下标。
    while(n > 1){
        int temp = a[pos].first;
        temp %= n;
        if(temp == 0)temp = n;
        pos = (pos + temp - 1) % n;
        //cout << pos << " " << a[pos].second << endl;
        for(int i = pos; i < n - 1; ++ i){
            a[i] = a[i + 1];
        }
        n --;
        pos %= n;
    }
    printf("%d\n", a[0].second);
}
int main(){
    scanf("%d", &n);
    for(int i = 0; i < n; ++ i){
        scanf("%d", &a[i].first);
        a[i].second = i + 1;
    }
    solve();
    return 0;
}

G.Out of Sorts

  • 题意
    给出一个序列构造参数,需要你构造出序列,并利用二分判断有多少个数可以用二分找到。

  • 解题思路
    按题意构造出序列,然后模拟二分操作即可。注意模拟二分这里需要使用递归,因为我们不知道内部构造,利用递归就可以处理好多情况。

  • AC代码

/**
  *@filename:G
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-22 21:47
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 1e6 + 5;
const int P = 1e9+7;

int n,m,a,c;
ll x[N];
int cal(int l, int r, ll num){
    if(l > r)return 0;
    int mid = l + r >> 1;
    if(x[mid] == num)return 1;
    if(num < x[mid]){
        return cal(l, mid - 1,num);
    }
    return cal(mid + 1, r, num);
}
void solve(){
    int ans = 0;
    for(int i = 1; i <= n; ++ i){
        ans += cal(1, n, x[i]);
    }
    cout << ans << endl;
}
int main(){
    cin >> n >> m >> a >> c >> x[0];
    for(int i = 1; i <= n; ++ i){
        x[i] = (x[i - 1] * a + c) % m;
    }
    solve();
    return 0;
}
posted @   unique_pursuit  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示