• Codeforces Round #428 (Div. 2) 题解


    题目链接:http://codeforces.com/contest/839

    A. Arya and Bran

    题意:每天给你一点糖果,如果大于8个,就只能给8个,剩下的可以存起来,小于8个就可以全部给完

    解法:水题,按照题意模拟一下即可。

    #include <bits/stdc++.h>
    using namespace std;
    int n, k, a[110];
    
    int main()
    {
        cin>>n>>k;
        int s = 0;
        for(int i=1; i<=n; i++){
            int x;
            cin >> x;
            s += x;
            x = min(s, 8);
            s -= x;
            k -= x;
            if(k<=0){
                cout<<i<<endl;
                return 0;
            }
        }
        cout<<-1<<endl;
        return 0;
    }
    
    B. Game of the Rows
    题意:将n批人安排进题目里给出的那种n行座位中,不同批的人只能隔着坐,问能不能安排下这些人

    解法:首先必然先安排大于等于3人的批次,将他们尽量安排在中间四连座的座位,安排不下了再安排在旁边两连座的,若也安排不下了,则必然输出NO,然后在安排剩余2个人的批次,先尽量安排在两连座的,若安排不下了则安排在中间四连座的,并且还可以安排边上坐一个人,若也安排不下,则将两个人拆开当作一个人去安排,最后判断座位够不够剩余1个人的批次即可

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 10010;
    int n, k, a[maxn], have[5], sum[5];
    
    int main()
    {
        while(~scanf("%d%d",&n,&k))
        {
            int flag=1;
            memset(sum,0,sizeof(sum));
            memset(have,0,sizeof(have));
            have[2]=2*n;
            have[4]=n;
            for(int i=0; i<k; i++) scanf("%d", &a[i]);
            for(int i=0; i<k; i++){
                while(a[i]>=3){
                    if(have[4]){
                        have[4]--;
                        a[i]-=4;
                    }
                    else if(have[2]){
                        have[2]--;
                        a[i]-=2;
                    }
                    else{
                        flag=0;
                        puts("NO");
                        break;
                    }
                }
                sum[a[i]]++;
            }
            while(sum[2]){
                if(have[2]){
                    have[2]--;
                    sum[2]--;
                }
                else if(have[4]){
                    have[4]--;
                    sum[2]--;
                    have[1]++;
                }
                else{
                    sum[2]--;
                    sum[1]+=2;
                }
            }
            if(flag){
                if(sum[1]>have[1]+have[2]+have[4]*2){
                    puts("NO");
                }
                else{
                    puts("YES");
                }
            }
        }
        return 0;
    }
    

     C. Journey

    题意:给你一颗树,设每两个节点间距离为1,从1开始,让你求这棵树的路程的期望

    解法:基础期望DP,逆推即可。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 100010;
    struct edge{
        int to,next;
    }E[maxn*2];
    int head[maxn],edgecnt, n;
    void init(){
        memset(head,-1,sizeof(head));
        edgecnt=0;
    }
    void add(int u, int v){
        E[edgecnt].to=v,E[edgecnt].next=head[u],head[u]=edgecnt++;
    }
    double dp[maxn];
    void dfs(int u, int fa){
        int cnt=0;
        dp[u] = 0;
        for(int i=head[u];~i;i=E[i].next){
            int v = E[i].to;
            if(v == fa) continue;
            dfs(v, u);
            dp[u] += dp[v];
            cnt++;
        }
        if(cnt!=0) dp[u] = dp[u]/cnt+1;
    }
    
    int main()
    {
        cin >> n;
        init();
        for(int i=1; i<n; i++){
            int u, v;
            scanf("%d %d", &u,&v);
            add(u,v);
            add(v,u);
        }
        dfs(1,-1);
        printf("%.10f
    ", dp[1]);
        return 0;
    }
    

     D. Winter is here

    题意:如果一个子序列的GCD为1,那么这个子序列的价值为0,否则子序列价值为子序列长度*子序列GCD。给出n个数,求这n个数所有子序列的价值和

    解法:



    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1000010;
    const int mod = 1e9+7;
    typedef long long LL;
    LL cnt[maxn],sum[maxn];
    LL qsm(LL a, LL n){
        LL ret=1;
        while(n){
            if(n&1) ret=ret*a%mod;
            a=a*a%mod;
            n/=2;
        }
        return ret;
    }
    int main()
    {
        int n;
        LL x, mx=0;
        scanf("%d", &n);
        for(int i=1; i<=n; i++){
            scanf("%lld", &x);
            mx = max(mx, x);
            cnt[x]++;
        }
        LL ans=0;
        for(int i=mx; i>=2; i--){
            x=0;
            for(int j=i; j<=mx; j+=i){
                sum[i]-=sum[j];
                x+=cnt[j];
            }
            sum[i]+=x*qsm(2LL,x-1)%mod;
            ans=((ans+sum[i]*i)%mod+mod)%mod;
        }
        printf("%lld
    ", ans);
        return 0;
    }
    

    E. Mother of Dragons

    题意:给了一个图,然后给了一个值,你可以把这个值分给有些点,对于一条边 u,v,价值是u的值乘以v的值吗,问如何分配可以使得值最大,问最大的值是多少。

    解法:参考题解:http://www.cnblogs.com/FxxL/p/7357221.html

    可以证明选最大团是最优解,所以套上求解最大团的模板就可以了。

    #include <bits/stdc++.h>
    using namespace std;
    #define N 110   //点从1到n
    bool g[N][N];
    int p, k;
    int que[N],cnt[N];//cnt[i]记录大于等于i的点集的最大团点数,i点可以不在其中
    int ans;//ans为最终最大团点数
    bool dfs(int pos,int num,int n)
    {
        for(int i=pos+1; i<=n; i++)
        {
            if(num+cnt[i]<=ans) return 0;
            //如果取i 但是cnt[i]也就是 >= i 的最大团点数 + 已经取了的点数还小于 ans, 剪枝
            if(g[pos][i])
            {
                int j;
                for(j=0; j<num; ++j) if(!g[i][ que[j] ]) break;
                if(j==num)
                {
                    que[num]=i;
                    if(dfs(i,num+1,n)) return 1;
                }
            }
        }
        if(num>ans)//因为每填加一个点最多使最大团数+1,后面的搜索就没有意义了
        {
            ans=num;
            return 1;//如果需要输出方案的话,此时的que内的点即为方案
        }
        return 0;
    }
    void solve(int n)
    {
        ans=0;
        for(int i=n; i>=1; i--)
        {
            que[0]=i;
            dfs(i,1,n);
            cnt[i]=ans;
        }
    }
    
    int main()
    {
        scanf("%d%d",&p,&k);
        for(int i=1; i<=p; i++){
            for(int j=1; j<=p; j++){
                scanf("%d", &g[i][j]);
            }
        }
        solve(p);
        double sum = 1.0*(ans)*(ans-1)/2*(1.0*k/ans)*(1.0*k/ans);
        printf("%.10f
    ", sum);
        return 0;
    }
    
  • 相关阅读:
    defineProperty的使用
    js题库全集
    如何将多个文件夹中的文件合并到一个文件夹中
    CYQ.Data V5 MDataTable 专属篇介绍
    读取和写入配置文件内容的方法
    面对代码中过多的if...else的解决方法
    SQL语句--删除掉重复项只保留一条
    获取当前时间
    Stopwatch 类用于计算程序运行时间
    正则表达式手册
  • 原文地址:https://www.cnblogs.com/spfa/p/7404521.html
Copyright © 2020-2023  润新知