zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    洛谷—— P2234 [HNOI2002]营业额统计
    BZOJ——3555: [Ctsc2014]企鹅QQ
    CodeVs——T 4919 线段树练习4
    python(35)- 异常处理
    August 29th 2016 Week 36th Monday
    August 28th 2016 Week 36th Sunday
    August 27th 2016 Week 35th Saturday
    August 26th 2016 Week 35th Friday
    August 25th 2016 Week 35th Thursday
    August 24th 2016 Week 35th Wednesday
  • 原文地址:https://www.cnblogs.com/zzyh/p/14496784.html
Copyright © 2011-2022 走看看