牛客IOI周赛22-普及组 题解

牛客IOI周赛22-普及组

简单得就nm离谱都ak不了,初中生的做的题,太丢人了。

T1 战争尾声

  • 题意:大体意思就是在一片网格图中,给(n)个点,然后找到一个点,这个点到所有点距离相同。(1 < n <= 200)并且所有点都是整数,并且地图大小(200 imes200)
  • 题解:看到范围就知道直接遍历就行,没啥好说的
  • 代码:
#include<iostream>
#include <cmath>
using namespace std;
 
const int N = 500;
int ans_cnt = 0;
const double eps = 1e-4;
struct node {
    double x, y;
}a[N];
 
struct Node {
    int x, y;
} ans[N*N+99];
bool equal(double a, double b) {
    return (fabs(a - b) < eps);
}
double dis(int X, int Y, node a) {
    double x = X, y = Y;
    return (a.x - x) * (a.x - x) + (a.y - y) * (a.y - y);
}
int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i].x >> a[i].y;
    }
    for (int Y = 1; Y <=200; Y++) {
        for (int X = 1; X <= 200; X++) {
            double x = X, y = Y;
            double Dis = dis(x, y, a[1]);
            bool f = 1;
            for (int i = 1; i <= n; i++) {
                if (!equal(Dis, dis(x, y, a[i]))) {
                    f = 0;
                    break;
                }
            }
            if (f) {
                ans[++ans_cnt] = { X, Y};
            }
        }
    }
    int MIx  = 2001;
    int MIy = 2020;
    int pos;
    for (int i = 1; i <= ans_cnt; i++) {
        if (ans[i].x < MIx) {
            MIx = ans[i].x;
            MIy = ans[i].y;
            pos = i;
        }   else if (ans[i].x == MIx) {
            if (ans[i].y < MIy) {
                MIy = ans[i].y;
                pos = i;
            }
        }
        if (i == ans_cnt) {
            cout << ans[pos].x << " " << ans[pos].y << endl;
        }
    }
    if (ans_cnt == 0)
    cout << "War is cruel.
";
    return 0;
}

T2 签订协议

  • 题意:给(n)个人,然后每个人都有权值,然后必须要从(1)(n)然后围成一圈遍历,遍历到权值最大的,把这人删除然后继续从下一人开始遍历,问遍历几次删除所有人。
  • 题解:把每个人的位置存一下,用权值关键字排个序从大到小,然后就遍历这个数组,如果下一个元素的位置比当前要小,那么(ans++),因为必然会转一圈,然后遍历一遍就行。
  • 代码:
#include <iostream>
#include <algorithm>

typedef long long ll;
using namespace std;



const ll N = 1e6 + 99;
struct node {
	int data, id;
	bool operator<(node rhs)const {
		return data > rhs.data;
	}
}a[N];
ll b[N];
signed main() {
	
	int n;
	
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i].data;
		a[i].id = i;
	}
	sort(a + 1, a + 1 + n);
	ll ans = 1;
	for (int i = 1; i <= n; i++) {
		b[i] = a[i].id;
		if (b[i] < b[i-1])ans++;
	}
	cout << ans << endl;	
}

T3 照看小猫

  • 题意:给(n)个小猫,要给这些猫起名字,每个猫名字要独一无二,(a_{i})表示第(i)个猫所能取的最长的长度,只能是小写字母(a)(z),求所有方案数。
  • 题解:一看到计数题自己就不自觉地和高深的容斥扯上关系。其实长度短的会对长度长的有影响,所以先排序。预处理出来一个小猫名字长度为(i)时的方案数,然后从前往后遍历数组,每次让(ans imes (cnt[i] - (i-1))),如果前面猫的数量太多,并且当前猫的名字长度太短,那么必然((cnt[i] - (i-1)) < 0)那么就没有办法了,无解。
  • 代码:
#include <iostream>
#include <algorithm>



using namespace std;
typedef long long ll;
const ll N = 1e5 + 9;
const ll mod = 77797;

ll q_mi(ll a, ll k, ll mod) {
	ll x = a;
	ll ret = 1;
	while (k) {
		if (k & 1) {
			(ret *= x)%= mod;
		}
		k>>=1;
		(x *= x)%= mod;
	}
	return ret;
}
ll a[N];
ll cost[11];
signed main() {
	ll n;
	cin >> n;
	for (ll i = 1; i <= 10; i++) {
		(cost[i] = q_mi(26, i, mod) + cost[i-1])%=mod;
	}
	ll ans = 1;
	for (ll i = 1; i <= n; i++) 
		cin >> a[i];
	sort(a + 1, a + 1 + n);
	for (ll i = 1; i <= n; i++) {
		if ( cost[a[i]] - (i-1) < 0) {
			cout << -1 << endl;return 0;
		}
		else {
			(ans *= (cost[a[i]] - ( i - 1)) )%= mod;
		}
	}
	cout << ans << endl;
}

T4 路线规划

  • 题意:给你一个(n imes m)的无向完全图,有边权,求从(1)要走到所有点并且走回(1),走最少的路,并且经过的边权加和最少。
  • 题解:随便搞了搞就发现是个最小生成树,因为走的路最少,那就是边的数量最少,又要遍历所有的边,所以是一个树,然后边权加和最少,那么走两边发现是最小生成树的边权(*2)
  • 代码:
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;


typedef long long ll;
const ll N  = 2e5 + 99;
const ll M = 2e6 + 99;
struct edge {
	int u, v, w;
}a[M];
bool cmp(edge a, edge b) {return b.w > a.w;
}

bool vis[N];

ll ans = 0;
ll f[N];
ll Find (ll x) {return f[x] == x?x:f[x] = Find(f[x]);}
signed main() {
	ll n, m;
	ios::sync_with_stdio(0);
	cin >> n >> m;
	for (int i = 1;i <= n; i++) {
		f[i] = i;
	}
	for (int i = 1; i<= m; i++) {
		int u, v, w;
		cin >> u >> v >> w;
		a[i] = {u, v, w};
	}
	sort(a + 1, a + 1 + m, cmp);
	for (int i = 1; i <= m; i++) {
		ll x = a[i].u;
		ll y = a[i].v;
		ll fx = Find(x);
		ll fy = Find(y);
		if (fx == fy)continue;
		f[fx] = fy;
		//cout << x << "?" << y << endl;
		ans += a[i].w;
	}
	cout << ans * 2 << endl;
}
原文地址:https://www.cnblogs.com/Xiao-yan/p/14315762.html