• 牛客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;
    }
    
  • 相关阅读:
    UVa 11181
    UVa 10491
    UVa 1636
    UVa 1262
    UVa 10820
    UVa 1635
    UVa 12716
    [2019杭电多校第六场][hdu6635]Nonsense Time
    [2019杭电多校第五场][hdu6630]permutation 2
    [2019杭电多校第五场][hdu6629]string matching(扩展kmp)
  • 原文地址:https://www.cnblogs.com/Xiao-yan/p/14315762.html
Copyright © 2020-2023  润新知