zoukankan      html  css  js  c++  java
  • 2019江西省程序设计竞赛

    A.Cotree

    题意:

    两棵树,你需要连接两个点使得(sum_{i=1}^{i=n}{sum_{j=i+1}^{j=n}}{dis(i,j)})最小。

    思路:

    对于每棵树进行换根dp,对每棵子树找到一个点使得所有点到这个点的距离和最小,连接这两个点,然后进行一次DFS统计每条边的贡献,累加即可。

    code

    #include<bits/stdc++.h>
    
    using namespace std;
    const int N = 1e5+100;
    vector<long long> G[N];
    int n,n1,n2;
    bool vis[N];
    long long ans;
    void dfs1(int x){
        if(vis[x]) return ;
        vis[x]=1;
        for(auto v:G[x]){
            dfs1(v);
        }
    }
    int ta,tb,now;
    long long dp[N];long long siz[N];
    void dfs2(long long u,long long fa){
        siz[u]=1;
        for(auto v:G[u]){
            if(v==fa) continue;
            dfs2(v,u);
            siz[u]+=siz[v];
            dp[u]+=dp[v];
        }
        dp[u]+=siz[u];
    }
    void dfs3(long long u,long long fa){
        if(ans>dp[u]){
            ans=dp[u];
            now=u;
        }
        for(auto v:G[u]){
            if(v==fa) continue;
            long long res=dp[u]-dp[v]-siz[v];
            dp[v]=(dp[v]+res+n1-siz[v]);
            dfs3(v,u);
        }
    }
    void dfs4(long long u,long long fa){
        if(ans>dp[u]){
            ans=dp[u];
            now=u;
        }
        for(auto v:G[u]){
            if(v==fa) continue;
            long long res=dp[u]-dp[v]-siz[v];
            dp[v]=(dp[v]+res+n2-siz[v]);
            dfs4(v,u);
        }
    }
    
    long long final=0;
    void dfs(int now,int fa){
        final+=siz[now]*(n-siz[now]);
        for(auto v:G[now]){
            if(v==fa) continue;
            dfs(v,now);
        }
    }
    int main(){
        //freopen("1.in","r",stdin);
        cin>>n;
        int u,v;
        for(int i=1;i<=n-2;i++){
            cin>>u>>v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        int a,b;//找到左子树的一个点和右子树的一个点
        a=1;dfs1(1);
        for(int i=2;i<=n;i++){
            if(!vis[i]){
                b=i;n2++;
            }
        }
        n1=n-n2;
        ans=99999999999999;
        now=a;
        dfs2(a,0);
        dfs3(a,0);
        ta=now;
        memset(dp,0,sizeof(dp));
        memset(siz,0,sizeof(siz));
        ans=99999999999999;
        now=b;
        dfs2(b,0);
        dfs4(b,0);
        tb=now;
        G[ta].push_back(tb);
        G[tb].push_back(ta);
        memset(dp,0,sizeof(dp));
        memset(siz,0,sizeof(siz));
        dfs2(1,0);
        dfs(1,0);
        cout<<final<<endl;
        return 0;
    }
    

    D.Wave

    题意:

    给一个数组,找到最长的一个子序列使得这个子序列的所有奇数位的数字相同,所有偶数位的数字相同,奇数位和偶数位的数字不同。

    思路:

    利用一个前缀和可以快速地查询([l,r])区间内(c)的数量,记录下每个数字出现的位置,暴力枚举子序列的那两个不同的数字,更新最大值。

    code

    #include<bits/stdc++.h>
    
    using namespace std;
    const int N = 1e6+100;
    vector<int> pos[200];
    int num[N][201];
    int a[N];
    int main(){
        int n,c;
        cin>>n>>c;
        for(int i=1;i<=100;i++){
            pos[i].push_back(0);
        }
        for(int i=1;i<=n;i++){
            cin>>a[i];
            pos[a[i]].push_back(i);
            for(int j=1;j<=100;j++) num[i][j]=num[i-1][j];
            num[i][a[i]]++;
        }
        int ans=0;
        for(int i=1;i<=c;i++){
            for(int j=1;j<=c;j++){
                if(i!=j){
                    int now=0;
                    for(int k=2;k<(int)pos[i].size();k++){
                        if(num[pos[i][k]][j]-num[pos[i][k-1]][j]>0) now++;
                    }
                    now=now*2+1;
                    if(num[n][j]-num[pos[i][(int)pos[i].size()-1]][j]>0){
                         now++;
                    }
                    ans=max(ans,now);
                }
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    

    F.String

    题意:

    给定一个字符串,随机拿出四个字母,求这四个字母组成"avin"的概率。

    思路:

    答案即为(frac{num['a']*num['v']*num['i']*num['n']}{|s|^4})

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    int main(){
        string s;int n;
        while(cin>>n>>s){
            long long a,b,c,d;
            a=b=c=d=0;
            for(int i=0;i<n;i++){
                if(s[i]=='a') a++;
                if(s[i]=='v') b++;
                if(s[i]=='i') c++;
                if(s[i]=='n') d++;
            }
            if(a*b*c*d==0){
                cout<<"0/1"<<endl;
            }
            else{
                long long x=a*b*c*d;
                long long y=(n*n*n*n);
                long long gg=__gcd(x,y);
                x/=gg;
                y/=gg;
                cout<<x<<'/'<<y<<endl;
            }
        }
        return 0;
    }
    

    G.Traffic

    题意:

    一个十字路口,东西和南北各有车辆经过,每个车到达十字路口的时间为(t_i),但是如果东西走向的汽车和南北走向的汽车同时到达十字路口,那么南北走向的就得等待。问最少要等多长时间。

    思路:

    暴力枚举等待时间,知道不会再有车发生时间冲撞。

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    const int N = 3000;
    long long a[N],b[N];
    bool ta[N],tb[N];
    int main(){
        int n,m;
        while(cin>>n>>m){
            memset(ta,0,sizeof(ta));
            memset(ta,0,sizeof(tb));
            for(int i=1;i<=n;i++) cin>>a[i],ta[a[i]]=1;
            for(int i=1;i<=m;i++) cin>>b[i];
            int res=999999999;
            for(int i=0;i<=1001;i++){
                int ans=0;
                bool flag=0;
                memset(tb,0,sizeof(tb));
                for(int j=1;j<=m;j++){
                    tb[b[j]+i]=1;
                    if(ta[b[j]+i]==1){
                        flag=1;break;
                    }
                }
                if(!flag){
                    res=i;break;
                }
            }
            cout<<res<<endl;
        }
        return 0;
    }
    

    H.Rng

    题意:

    一个([1,n])的区间,执行下列操作:
    1.任意在([1,n])中选择一个(r)
    2.在([1,r])中选择一个(l)
    计算两次线段相交的概率

    思路:

    手动计算2的情况为(frac{3}{4}),暴力打表发现接近(frac{1}{2}),猜测答案为(frac{n+1}{2*n})

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    const int mod = 1e9+7;
    long long qp(long long a,long long b){
        long long ans=1;
        while(b){
            if(b&1){
                ans=(ans%mod*a%mod)%mod;
            }
            a=(a%mod*a%mod)%mod;
            b>>=1;
        }
        return ans;
    }
    int main(){
        int n;
        while(cin>>n){
            cout<<((n+1)%mod*qp(2*n,mod-2)%mod)%mod<<endl;
        }
        return 0;
    }
    

    I.Budget

    题意:

    (n)个保留三位的小数,计算他们四舍五入变为2位后的差值

    思路:

    以string读入,判断最后一位即可。

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    const int N = 2000000;
    string a[N];
    int main(){
        int n;
        while(cin>>n){
            double ans=0;
            for(int i=1;i<=n;i++){
                cin>>a[i];
                int l=(int)a[i].length();
                if(a[i][l-1]<='4'){
                    ans-=((a[i][l-1]-'0')*1.0)/(1000);
                }
                else{
                    ans+=((10-(a[i][l-1]-'0'))*1.0)/1000;
                }
            }
            printf("%.3lf
    ",ans);
        }
        return 0;
    

    J.Worker

    题意:

    (n)个工作间,(m)个人,第(i)个工作间每个人每天的产量位(a_i),计算一种分配方案使的每个工作间的产量相同,如果没有,输出"No"。

    思路:

    (lcm)分配即可。

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    const int N = 3000;
    long long lcm(long long a,long long b){
       return a*b/__gcd(a,b);
    }
    int a[N],b[N];
    int main(){
       long long n,m;
       while(cin>>n>>m){
           long long all=1;
           for(int i=1;i<=n;i++) cin>>a[i],all=lcm(all,a[i]);
           long long zz=0;
           for(int i=1;i<=n;i++){
               b[i]=all/(a[i]);
               zz+=b[i];
           }
           if(m%zz){
               cout<<"No"<<endl;
           }
           else{
               cout<<"Yes"<<endl;
               for(int i=1;i<=n-1;i++) cout<<m/(zz)*b[i]<<' ';
               cout<<(m/zz)*b[n]<<endl;
           }
       }
    }
    

    K.Class

    题意:

    (x=a+b,y=a-b)
    计算(a*b)

    思路:

    答案为(frac{(x+y)*(x-y)}{4})

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    int main(){
       long long x,y;
       cin>>x>>y;
       cout<<(x+y)*(x-y)/4<<endl;
       return 0;
    }
    
  • 相关阅读:
    hibernate执行createSQLQuery时字段重名的问题
    注意JDBC驱动的版本和JDK的版本是否匹配 JDBC连接Mariadb
    MariaDBConn用于链接MariaDB的管理类
    PLSQL Developer对oracle中的数据进行备份恢复
    JQuery判断浏览器类型
    IE与非IE window.onload调用
    如何升级centos到最新版本
    bootstrap 后台模板
    FontAwesome 4.7.0 中完整的675个图标样式CSS参考
    Linux Crontab及使用salt进行管理
  • 原文地址:https://www.cnblogs.com/codancer/p/12232386.html
Copyright © 2011-2022 走看看