牛客IOI周赛22-普及组 (被自己菜到了)

后话,

一个 2 6 10 26^{10} 2610会爆longlong吗??????????
我真的qwqwqw…qwq(赛中走上了高精度,一直wa到哭qwq)

A战争尾声

题意:

有n个点(x,y)且范围都是 ( 1 , 200 ) (1,200) (1,200),现在要你找到一个点,使得它到所有其他点的距离最小。
n的范围也只有200。
输出
最小的点

思路:

由于n小,直接暴力枚举答案即可。(根据横纵坐标即可)

AC

# include <bits/stdc++.h>
# define fi first
# define se second 
# define mp make_pair
using namespace std;
const int N = 220;
const double eps = 1e-4;
typedef pair<int,int>pa;
int n;
pa point[N];
double getdis(int i, pa x){
    
    
    return sqrt( (point[i].fi-x.fi)*(point[i].fi-x.fi) + (point[i].se-x.se)*(point[i].se-x.se) );
}
void init(){
    
    
    cin>>n;
    for(int i = 1; i <= n; i ++ )cin>>point[i].fi>>point[i].se;
}
const string no="War is cruel.";
bool check(pa p){
    
    
    double dis = getdis(1,p);
    for(int i = 2; i <= n; i ++ ){
    
    
        if(fabs(dis-getdis(i,p))>eps)return false;
    }
    return true;
}
void sol(){
    
    
    bool ok = false;
    for(int x = 1;x <=200&&!ok; x++ ){
    
    
        for(int y = 1;y <= 200&&!ok; y ++ ){
    
    
            pa p = {
    
    x,y};
            if(!check(p))continue;
            ok = true;
            cout<<x<<' '<<y<<endl;
           // break;
        }
    }
    if(!ok)cout<<no<<endl;
}
int main(){
    
    
    ios::sync_with_stdio(0);
    //int n;
    init();
    sol();
    return 0;    
}

B 签订协议

题意:

在这里插入图片描述

思路1(优先队列nlogn)

可以考虑用一个优先队列,去维护,战力最高的在队首。
之后每次出队,就行了。假如当前top的位置 在pre的前面,那么ans++。

AC1

# include <bits/stdc++.h>
# define fi first
# define se second
# define mp make_pair
# define pb push_back
using namespace std;
typedef pair<int,int>pa;
priority_queue<pa> q;
int main(){
    
    
    ios::sync_with_stdio(0);
    int n;
    cin>>n;
    int x;
    for(int i = 1; i <= n; i ++ ){
    
    
        cin>>x;
        q.push(mp(x,i));
    }
    int pre = n+1, ans = 0;
    while(!q.empty()){
    
    
        int idx = q.top().se;
        q.pop();
        if(idx<pre)ans++;
        pre = idx;
    }
    cout<<ans<<endl;
    return 0;
}

思路2(离散化nlogn)

先把数组离散化,之后暴力枚举,每个战力最小的元素(这一步可以On查询)。
其实代码,和上面差不多,只不过是,先预处理出了战力的顺序。

AC2

# include <bits/stdc++.h>
using namespace std;
const int N = 8e5+10;
int pa[N], a[N], lx[N];
int main(){
    
    
    //ios::sync_with_stdio(0);
    int n;
    scanf("%d", &n);//cin>>n;
    for(int i = 1; i <= n; i ++ )scanf("%d", a+i),lx[i] = a[i];
    sort(lx+1,lx+1+n);
    for(int i = 1; i <= n; i ++ )a[i] = lower_bound(lx+1,lx+1+n,a[i])-lx, pa[a[i]] = i;
    int res = 0, pre = n+1;
    for(int i = n; i >= 1; i -- ){
    
    
        if(pa[i]<pre)res++;
        pre = pa[i];
    }
    printf("%d\n", res);//cout<<res<<endl;
    return 0;
}

C照看小猫

题意:

在这里插入图片描述

思路:

简单组合数学,

  1. 用桶排序预处理。
  2. 之后查看每个长度所能构成的解的个数,加入不够就break。

AC

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
/*
bool isprime(int x){
    for(int i = 2; i<=x/i; i ++ )if(x%i==0)return false;
    return true;
}
*/
const int N = 1e4+10;
int inv[N];
int fac[N];
const int mod = 77797;
typedef long long ll;
/*
void table(){
    //for(int i = 1; i < N; i ++ )
}
*/
ll n, vis[20];
int main(){
    
    
    //cout<<(isprime(77797));
    ios::sync_with_stdio(0);
    cin>>n;
    int x;
    for(int i = 1; i <= n; i ++ )cin>>x,vis[x]++;
    ll ans = 1, sum = 0;
    bool ok = true;
    ll xx = 1;
    for(int i = 1; i <= 10; i ++ ){
    
    
        xx = xx*26;
        //cout<<vis[i]<<endl;
        sum += xx;
        if(sum < vis[i]){
    
    
            ok = false;
            break;
        }
        for(int j = 1; j <= vis[i]; j ++ ){
    
    
            ans = ans * (sum%mod) % mod;
            sum -= 1;
        }
    }
    if(ok)cout<<ans<<endl;
    else cout<<-1<<endl;
    return 0;
}

D路线规划

题意:

在这里插入图片描述

思路

建立最小生成树,就好。之后ans*2.

AC

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
const int M = N*10;
struct Edge{
    
    
    int u, v;
    ll w;
} e[M];
int f[N];
int find(int x){
    
    
    if(x==f[x])return x;
    return f[x] = find(f[x]);
}
int n, m;
void init(){
    
    
    scanf("%d%d", &n, &m);//cin>>n>>m;
    for(int i = 1; i <= m; i ++ ){
    
    
        int u, v;
        ll w; 
        scanf("%d%d%lld", &u, &v, &w);
        e[i] = {
    
    u,v,w};
    }
}
void sol(){
    
    
    sort(e+1,e+1+m,[&](Edge a, Edge b){
    
    
        return a.w<b.w;
    });
    ll res = 0;
    for(int i = 1; i <= n; i ++ )f[i] = i;
    int tot = 1;
    for(int i = 1; i <=m; i ++ ){
    
    
        int u=e[i].u,v=e[i].v;
        ll w = e[i].w;
        int A = find(u), B = find(v);
        if(A==B)continue;
        f[A] = B;
        res += w;
        tot++;
        if(tot==n)break;
    }
    printf("%lld\n", 2*res);
}
int main(){
    
    
    init();
    sol();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45377553/article/details/113009105