2021年度训练联盟热身训练赛第一场

A Weird Flecks, But OK

链接https://ac.nowcoder.com/acm/contest/12606/A
题意
给定若干个空间中的点,求从三个标准空间直角坐标平面进去能够全部覆盖这些点的最小半径
题解

注意
代码

#include<bits/stdc++.h>
using namespace std;
#define N 1e5+5;
#define INF 99999999;
#define eps 1e-6
#define powe(x) (x)*(x)
struct point{
    double x,y;
}p[5005],O;
struct Data{
    double  x,y,z;
}data[5005];//点集
double R;//半径
int n;
double getd(point a,point b)
{
    return sqrt(powe(a.x-b.x)+powe(a.y-b.y));
}
point getO(point p1,point p2,point p3) {
    point res;
    double a = p2.x - p1.x;
    double b = p2.y - p1.y;
    double c = p3.x - p2.x;
    double d = p3.y - p2.y;
    double e = powe(p2.x) + powe(p2.y) - powe(p1.x) - powe(p1.y);
    double f = powe(p3.x) + powe(p3.y) - powe(p2.x) - powe(p2.y);
    res.x = (f * b - e * d) / 2.0 / (c * b - a * d);
    res.y = (f * a - e * c) / 2.0 / (d * a - b * c);//利用数学推导
    return res;//res即为所求的圆心
}
void min_cir()
{
    O=p[1];
    R=0;
    for(int i=1;i<=n;i++)
    {
        if(getd(p[i],O)-R>eps){//点在圆外
            O=p[i];//一个点在外边
            R=0;
            for(int j=1;j<i;j++)
            {
                if(getd(p[j],O)-R>eps)
                {
                    O={(p[i].x+p[j].x)/2.0,(p[i].y+p[j].y)/2.0};//有两个点在圆的外边,求法
                    R=getd(p[i],p[j])/2.0;
                }
                for(int k=1;k<j;k++)
                {
                    if(getd(p[k],O)-R>eps)
                    {
                        O=getO(p[i],p[j],p[k]);//三个点都在圆的外边
                        R=getd(O,p[i]);
                    }
                }
            }
        }
    }
}//不断更新迭代得到的是能够包含p[i]所有点的最小圆
int main()
{
    cin>>n;double a,b,c;
    for(int i=1;i<=n;i++)
        cin>>data[i].x>>data[i].y>>data[i].z;
    random_shuffle(data+1,data+1+n);
    for(int i=1;i<=n;i++)p[i].x=data[i].x,p[i].y=data[i].y;
    min_cir();
    a=R;
    for(int i=1;i<=n;i++)p[i].x=data[i].x,p[i].y=data[i].z;
    min_cir();
    b=R;
    for(int i=1;i<=n;i++)p[i].x=data[i].y,p[i].y=data[i].z;
    min_cir();
    c=R;
    printf("%lf",2*min(a,min(b,c)));
    return 0;
}

参考https://ac.nowcoder.com/acm/contest/view-submission?submissionId=47553313

B Code Names

链接https://ac.nowcoder.com/acm/contest/12606/B
题意
两两之间有两个字符不同的则可以进行配对,求最小的不配对子集的个数(n-组合优化最大个数)
题解
匈牙利算法,求组合优化
注意
swap-free永远的神
代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
string data[10005];
vector<int>p[10005];
int pre[10005],vis[10005];
bool check(string a,string b)
{
    int x=a.size(),y=b.size();
    if(x!=y)return 0;
    int n=0;
    for(int i=0;i<x;i++)
    if(a[i]!=b[i])n++;
    if(n==2)return 1;
    else return 0;
}
bool dfs(int x){
    for(auto to:p[x]){
        if(vis[to])continue;
        vis[to]=1;
        if(!pre[to]||dfs(pre[to])){
            pre[to]=x;
            return 1;
        }
    }
    return 0;
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>data[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            if(check(data[i],data[j])){
                p[i].push_back(j);
                p[j].push_back(i);
            }
        }
    }
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        memset(vis,0,sizeof(vis));
        if(dfs(i))cnt++;
    }
    printf("%d",n-cnt/2);
    return 0;
}

参考https://ac.nowcoder.com/acm/contest/view-submission?submissionId=47499518

C New Maths

链接https://ac.nowcoder.com/acm/contest/12606/C
题意
求某个数乘法加法(乘以自己)均不进位得到的某给定的数,若是找不到则输出-1
题解
爆搜
注意
注意若a(*)a=N,a数位为n,则N数位必为2n-1;
代码

#include<bits/stdc++.h>
using namespace std;
string s;int a[30];
void dfs(int pos,int len)
{
    if(pos>len){
        for(int i=1;i<=pos/2;i++)
        {
            cout<<a[i];
        }
        exit(0);
    }
    for(int i=0;i<=9;i++)
    {
        a[pos]=i;
        int c=0;
        for(int j=1;j<=pos;j++)
        {
            c+=(a[j]*a[pos-j+1]);
            c%=10;
        }
        if(c+'0'==s[pos-1])dfs(pos+1,s.size());
    }
}
int main(){
    cin>>s;
    if(s.size()&1)dfs(1,s.size());
    printf("-1");
    return 0;
}

参考https://ac.nowcoder.com/acm/contest/view-submission?submissionId=47487564

D Some Sum

链接https://ac.nowcoder.com/acm/contest/12606/E
题意
n个连续的数相加,他们的和若一定是偶数,输出even,若一定是奇数输出odd,若即可能是偶数也可能是奇数则输出either
题解
注意
注意分情况讨论
代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;cin>>n;
    if(n%2==1)printf("Either");
    else {
        if(n%4==0)printf("Even");
        else printf("Odd");
    }
    return 0;
}

E Early Orders

链接https://ac.nowcoder.com/acm/contest/12606/E
题意
给定n个一连串从1到k的数字,求这些数字的字串里边字典序最小的序列(字串可以不连续,但是需包含从1到k的所有数字)
题解
条件排除,制造序列
当前这个数比后一个大,且它的最大下标大于后一个下标,则需要被踢出,且数列里头只容许不相同的数字存在
注意
代码

#include<bits/stdc++.h>
using namespace std;
int rray[200005],last[200005],vis[200005],ans[200005];
int main()
{

    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>rray[i];
        last[rray[i]]=i;//数字最后的编号
    }
    for(int i=1,j=0;i<=n;i++)
    {
        if(vis[rray[i]])continue;//已经把rray[i]放进了序列里头(该序列里已经是当前的最小字典序
        while(ans[j]>rray[i]&&last[ans[j]]>i){
            vis[ans[j--]]=0;//发现之前一个数字不符合条件,踢出该数字
        }//表示的是ans[j]的位置是大于i的
        ans[++j]=rray[i];//先填数字进去
        vis[rray[i]]=1;

    }
    for(int i=1;i<=k;i++)
        printf("%d ",ans[i]);
        return 0;
}

参考https://ac.nowcoder.com/acm/discuss/blogs?tagId=140551

F Pulling Their Weight

题意
把小动物的体重尽可能均匀的分配,求这个依据分配的数值
题解
类似于将小动物的质量分成两半,尽可能数值是平均,再去找中间可能的临界值。
注意
注意刚好平均分配和稍微有一些误差的情况
代码

#include<bits/stdc++.h>
using namespace std;
int weight[100005],temp[100005];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>weight[i];
    sort(weight+1,weight+n+1);
    for(int i=1;i<=n;i++)
    {
        temp[i]+=temp[i-1]+weight[i];//得到一个前缀和序列
    }
    int ans=temp[n]/2;
    int x=lower_bound(temp+1,temp+n+1,ans)-temp;
    int ansl=temp[x],ansr=temp[n]-temp[x];
    if(ansl==ansr){
        if(weight[x]!=weight[x+1])printf("%d",weight[x]+1);
        else printf("%d",weight[x]);
    }
    else
    {
        printf("%d",weight[x]);
    }
    return 0;
}

G Birthday Paradox

链接https://ac.nowcoder.com/acm/contest/12606/G
题意
排列组合求解数学问题
题解
概率论数学知识
注意
可以先进行log操作,降低数据长度;注意数据的初始化问题
代码

#include<bits/stdc++.h>
using namespace std;
//概率论的计算题,嘤嘤嘤
//=m!n!c(365,n)/365^m/d!/f!
//log10(m!)+log(n!)+log(365)-log(连乘d)-log(连乘f)-log(365-n!)-log(n!)-mlog(365);
int c[550],G[550];
double f[36500];
void init()
{
    f[0]=0;
    f[1]=0;
    for(int i=2;i<=36500;i++)
        f[i]=f[i-1]+log10(1.0*i);
}
int main()
{
    init();
    int n,m=0;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>c[i];
        m+=c[i];
        G[c[i]]++;
    }
    double ans=f[365]+f[m];
    ans-=f[365-n];
    ans-=m*log10(365);
    for(int i=0;i<n;i++)ans-=f[c[i]];
    for(int i=1;i<101;i++)ans-=f[G[i]];
    printf("%.15lf",ans);
    return 0;
}

参考https://ac.nowcoder.com/acm/contest/view-submission?submissionId=47261409

H On Average They're Purple

链接https://ac.nowcoder.com/acm/contest/12606/H
题意
题解
最短路径-1
代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,a,b,vis[N],dis[N];
vector<int>node[N];
queue<int>q;
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        cin>>a>>b;
        node[a].push_back(b);
        node[b].push_back(a);
    }
    q.push(1);
    vis[1]=1;
    while(q.size())
    {
        int now=q.front();
        q.pop();
        for(int t:node[now])
        {
            if(vis[t])continue;
            vis[t]=1;
            dis[t]=dis[now]+1;
            q.push(t);
        }
    }
    printf("%d",dis[n]-1);
    return 0;
}
posted @ 2021-05-05 21:53  Aaryn21  阅读(78)  评论(0)    收藏  举报