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


    传送门:https://ac.nowcoder.com/acm/contest/12606#question

    A题 Weird Flecks, But OK

    题解:计算几何 最小圆覆盖问题

    B题 Code Names

    题解:建图+匈牙利算法   最大团=补图的最大独立集  最大独立集=点数-最大匹配/2

    C题 New Maths

    题解:搜索

    D Some Sum

    题解:签到题  暴力

    E Early Orders

    题解:栈模拟

    F Pulling Their Weight

    题解:签到题

    G Birthday Paradox

    题解:组合数学

    H On Average They're Purple

    题解:最短路

    J This Ain't Your Grandpa's Checkerboard

    题解:模拟

     

    A把点投到三个平面,做三次最小点覆盖。 

    #include<bits/stdc++.h>
    using namespace std;
    
    #define N 5210
    #define pf(x) ((x)*(x))
    #define eps 1e-6
    int n;
    double x[N],y[N],z[N];
    double R;
    struct point
    {
        double x,y;
    }p[N],O;
    //求两点间的距离 
    double getdis(point a,point b)
    {
        return sqrt(pf(a.x-b.x)+pf(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=pf(p2.x)+pf(p2.y)-pf(p1.x)-pf(p1.y);
        double f=pf(p3.x)+pf(p3.y)-pf(p2.x)-pf(p2.y);
        res.x=(f*b-e*d)/(c*b-a*d)/2.0; 
        res.y=(a*f-e*c)/(a*d-b*c)/2.0; 
        return res; 
    }
    
    void slove()
    {
        O=p[1];R=0;
        for(int i=1;i<=n;i++)
        {
            if(getdis(p[i],O)-R>eps)
            {
                O=p[i];R=0;
                for(int j=1;j<i;j++)
                {
                    if(getdis(p[j],O)-R>eps)
                    {
                        O=(point){(p[i].x+p[j].x)/2.0,(p[i].y+p[j].y)/2.0};
                        R=getdis(p[i],p[j])/2.0;
                        for(int k=1;k<j;k++)
                        {
                            if(getdis(p[k],O)-R>eps)
                            {
                                O=getO(p[i],p[j],p[k]);
                                R=getdis(p[i],O);
                            }
                        }
                    }
                }
            }
        }
    }
    
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++) cin>>x[i]>>y[i]>>z[i];
        double ans=100000;
        for(int i=1;i<=n;i++) p[i].x=x[i],p[i].y=y[i];
        random_shuffle(p+1,p+1+n);
        slove();
        if(ans-R>eps) ans=R;
        for(int i=1;i<=n;i++) p[i].x=x[i],p[i].y=z[i];
        random_shuffle(p+1,p+1+n);
        slove();
        if(ans-R>eps) ans=R;
        for(int i=1;i<=n;i++) p[i].x=y[i],p[i].y=z[i];
        random_shuffle(p+1,p+1+n);
        slove();
        if(ans-R>eps) ans=R;
        printf("%.10f",2*ans);
    }
    View Code

     B

    将不能通过一次交换就变成对方的字符串连线,发现答案是最大完全子图

    建立上图的补图,即 将能通过交换就变成对方的字符串连线建图,求最大匹配数。

    最大完全子图=补图的最大独立集=点数-最大匹配/2

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 1000001
    using namespace std;
    
    int n,sumedge,cnt;
    int head[maxn],vis[maxn],match[maxn];
    string s[maxn];
    
    struct Edge{
        int x,y,nxt;
        Edge(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }edge[maxn<<1];
    
    void add(int x,int y){
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    
    bool pipei(int x){
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(vis[v]==0){
                vis[v]=1;
                if(!match[v]||pipei(match[v])){
                    match[v]=x;return true;
              }
           }
        }return false;
    }
    
    void INit()
    {
        scanf("%d",&n);
        int len;
        for(int i=1;i<=n;i++) cin>>s[i];
        len=s[1].length();
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                int js=0;
                for(int k=0;k<len;k++)
                {
                    if(s[i][k]!=s[j][k]) js++;
                } 
                if(js<3) 
                {
                    add(i,j);
                    add(j,i);
                //    cout<<i<<"--"<<j<<endl;
                } 
            } 
        }
    }
    int main()
    {
        INit();
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof(vis));
            if(pipei(i)) ans++;
         } 
         cout<<n-ans/2;
        return 0;
    }
    View Code

    C

    搜索 枚举a的每一位

    #include<bits/stdc++.h>
    using namespace std;
    
    #define N 55
    
    int len;
    int a[N];
    char s[N];
    bool flag;
    
    void dfs(int now)
    {
        if(now>len&&!flag)
        {
            int gg=(len+1)/2;
            flag=1;
            for(int i=1;i<=gg;i++)
            {
                cout<<a[i];
            }
            return ;
        }
        for(int i=0;i<=9;i++)
        {
            a[now]=i;
            int sum=0;
            for(int j=1;j<=now;j++)
            {
                sum=sum+a[j]*a[now-j+1];
            }
            if(sum%10==s[now]-'0') dfs(now+1);
        }
    }
    
    int main()
    {
        scanf("%s",s+1);
        len=strlen(s+1);
        if(len%2==0)
        {
            cout<<"-1
    ";
            return 0; 
        }
        dfs(1);
        if(!flag)
        {
            cout<<"-1";
        }
        return 0;
    }
    View Code

    D

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        int n;
        cin>>n;
        bool ou=0,ji=0;
        for(int i=1;i<=100;i++)
        {
            int sum=0;
            for(int j=i;j<=i+n-1;j++)
            {
                sum=sum+j;
            }
            if(sum%2==0)ou=1;
            if(sum%2==1)ji=1;
        } 
        if(ou==1&&ji==1) cout<<"Either";
        if(ou==1&&ji==0) cout<<"Even";
        if(ou==0&&ji==1) cout<<"Odd"; 
        return 0;
    } 
    
    /*
    
    */ 
    View Code

    E

    维护一个栈

    1)当前数在栈中,不做操作

    2)当前数不在栈中时

    若当前数比栈顶小,且栈顶的数在后面还会再出现,栈顶的数出栈,当前数进栈

     代码队友写的

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<stack>
    using namespace std;
    int s[200050]={0};
    int flag[200050]={0};
    stack<int>st;
    int vis[200050]={0};
    int ans[200050]={0};
    int main()
    {
        int n,k;
        cin>>n>>k;
        int i;
        for(i=0;i<n;i++)
        {
            cin>>s[i];
        }
        int len=n;
        for(int i=0;i<len;i++)
        {
            flag[s[i]]++;//计算数量 
        }
        st.push(s[0]);
        vis[s[0]]=1;//标记 
        flag[s[0]]--;
        for(int i=1;i<len;i++)
        {
            flag[s[i]]--;
            if(vis[s[i]])//在栈内,就不用操作,直接下一个元素 
                continue;
            while(!st.empty()&&st.top()>s[i]&&flag[st.top()]>0)//s[i]比栈顶元素小且后面还有栈顶元素,则出栈 
            {
                vis[st.top()]=0;
                st.pop();
            }
            st.push(s[i]);//没有标记的进栈 
            vis[s[i]]=1;    
        }    
        int sum=0;
        while(!st.empty())
        {
            if(ans[sum]!=st.top())
            {
                ans[sum++]=st.top();
            }
            st.pop();
        }
        for(int i=sum-1;i>=0;i--)//倒序输出 
        {
            if(ans[i]!=ans[i+1])
            {
                cout<<ans[i]<<' ';
            }
        }
    } 
    View Code

    F

    略 队友代码

    #include<iostream>
    using namespace std;
    long long n,i,x,sum1=0,sum2=0,a[20005],t,u;
    
    int main()
    {cin.tie(0);ios::sync_with_stdio(false);
        cin>>n;
        for(i=1;i<=n;i++)
        {
            cin>>x;
            sum1+=x;
            a[x]++;
        }
        for(i=1;i<=20000;i++)
        {
            if(a[i]>0)
            {
                if(a[i]%2==0) {t=sum2+a[i]/2*i;if(t*2==sum1) {cout<<i<<endl;return 0;}}
                else
                {
                    t=sum2;
                    u=sum1-sum2-a[i]*i;
                    if(t==u){cout<<i<<endl;return 0;}
                }
            }else
            {
                t=sum2;
                if(t*2==sum1) {cout<<i<<endl;return 0;}
            }
            sum2+=a[i]*i;
        }
        
        return 0;
    }
    View Code

    G

    把上面式子拆开算就行
    #include<bits/stdc++.h>
    using namespace std;
    #define N 520
    
    int n,m;
    double Log[100000];
    int d[N],c[N];
    double ans;
    
    double log10(int x)
    {
        return log(x)/log(10);
    }
    
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
        cin>>n;
        for(int i=1;i<100000;i++) Log[i]=Log[i]+Log[i-1]+log10(i);
        for(int i=1;i<=n;i++) cin>>c[i],d[c[i]]++,m+=c[i];
        ans=Log[365]-Log[365-n]-Log[n]+Log[m]+Log[n]-m*log10(365);
        for(int i=1;i<=n;i++) ans=ans-Log[c[i]];
        for(int i=1;i<=100;i++) ans=ans-Log[d[i]];
        printf("%.15lf",ans);
        return 0;
    }
    View Code

    H

    发现最小颜色改变次数为 1到n的最短路径长度-1

    求最短路用的优化后的狄杰斯特拉

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #define N 100008
    using namespace std;
    
    int n,m,s;
    
    int sumedge;
    
    int head[N],dis[N],vis[N];
    
    struct Edge{
        int x,y,z,nxt;
        Edge(int x=0,int y=0,int z=0,int nxt=0):
            x(x),y(y),z(z),nxt(nxt){}
    }edge[N*2];
    
    struct node{
        int x,dis;
        bool operator < (node a) const{
            return dis>a.dis;
        }
    };
    
    priority_queue<node>q;
    
    void add(int x,int y,int z){
        edge[++sumedge]=Edge(x,y,z,head[x]);
        head[x]=sumedge;
    }
    
    void dijikstra(int x){
        while(!q.empty())q.pop();
        memset(dis,0x3f,sizeof(dis));
        dis[x]=0;
        q.push((node){x,0});
        while(!q.empty()){
            node now=q.top();q.pop();
            if(vis[now.x])continue;
            vis[now.x]=true;
            for(int i=head[now.x];i;i=edge[i].nxt){
                int v=edge[i].y;
                if(dis[v]>dis[now.x]+edge[i].z){
                    dis[v]=dis[now.x]+edge[i].z;
                    q.push((node){v,dis[v]}); 
                }
            }
        } 
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y,1);
            add(y,x,1);
        }
        dijikstra(1);
        cout<<dis[n]-1;
        return 0;
    }
    View Code

    J

    简单模拟

    #include<bits/stdc++.h>
    using namespace std; 
    
    int n;
    char s[25][25];
    
    bool check1()
    {
        int cnt1=0,cnt2=0,cntb=0;
        for(int j=1;j<=n;j++)
        {
            if(s[1][j]=='B') 
            {
                cnt1++,cntb++;
                if(cnt2>=3) return 0;
                cnt2=0;
            }
            else 
            {
                if(cnt1>=3) return 0;
                cnt1=0;
                cnt2++;
            }
        } 
        if(cntb==n) return 0;
        int jsb=0;
        for(int i=1;i<=n;i++)
        {
            jsb=0;cnt1=0;cnt2=0;
            for(int j=1;j<=n;j++)
            {
                if(s[i][j]=='B') 
                {
                    cnt1++,jsb++;
                    if(cnt2>=3) return 0;
                    cnt2=0;
                }
                else
                {
                    if(cnt1>=3) return 0;
                    cnt1=0;cnt2++;
                } 
            }
            if(jsb!=cntb) return 0;
        }
        return 1;
    }
    
    bool check2()
    {
        int cnt1=0,cnt2=0,cntb=0;
        for(int j=1;j<=n;j++)
        {
            if(s[j][1]=='B') 
            {
                cnt1++,cntb++;
                if(cnt2>=3) return 0;
                cnt2=0;
            }
            else 
            {
                if(cnt1>=3) return 0;
                cnt1=0;
                cnt2++;
            }
        } 
        if(cntb==n) return 0;
        int jsb=0;
        for(int i=1;i<=n;i++)
        {
            jsb=0;cnt1=0;cnt2=0;
            for(int j=1;j<=n;j++)
            {
                if(s[j][i]=='B') 
                {
                    cnt1++,jsb++;
                    if(cnt2>=3) return 0;
                    cnt2=0;
                }
                else
                {
                    if(cnt1>=3) return 0;
                    cnt1=0;cnt2++;
                } 
            }
            if(jsb!=cntb) return 0;
        }
        return 1;
    }
    
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>(s[i]+1);
        }
        if(check1()==0)
        {
            cout<<"0
    ";
            return 0;
        }
        if(check2()==0)
        {
            cout<<"0
    ";
            return 0;
        }
        cout<<"1";
        return 0;
    }
    View Code
  • 相关阅读:
    HDOJ 5414 CRB and String 模拟
    Python标准库:内置函数all(iterable)
    Can not find a java.io.InputStream with the name [downloadFile] in the invocation stack.
    关于TabLayout+ViewPager组合实现多页面滑动
    互联网产品经理应该具备的技能(需求篇)
    【Android】利用自己定义View的重绘实现拖动移动,获取组件的尺寸
    mybatis自己主动生成mapper,dao,映射文件
    Java解析注解
    如日中天的Uber到底是用什么开发语言做到的?
    [Swift]LeetCode1002. 查找常用字符 | Find Common Characters
  • 原文地址:https://www.cnblogs.com/zzyh/p/14496784.html
Copyright © 2020-2023  润新知