zoukankan      html  css  js  c++  java
  • Codeforces Round #263 (Div. 1) 题解

    A:Appleman and Toastman

    题意:两个人玩游戏 初始第一个人给第二个人一个数组 第二个人把数组中每个数相加的和加到他的总得分里面,然后把这个数组还给第一个人,第一个人进行操作:若数组中只剩下一个数,就把这个数组扔了,否则把这个数组拆成两个数组扔回给第二个人,求第二个人的最大得分。

    题解:游戏结束即为数组中N个数全被拆成了单独的一个数,而且我们可以知道若一个数在第一个人操作第K次时候变成只有一个数的数组,那么这个数在第二个人那算了K+1次,于是不难想到贪心算法,即让越大的数算的次数越多,于是从小到大排序后,第I个数在第I次变成单独的数组,于是第I个数被算了I+1次,注意最后一次是把第N-1和N个数都变成了单独的,于是最后两个数都是被算了N次,问题得到解决。

     1 #include <cstdio>
     2 
     3 #include <cmath>
     4 
     5 #include <iostream>
     6 
     7 #include <cstring>
     8 
     9 #include <algorithm>
    10 
    11 
    12 
    13 using namespace std;
    14 
    15 long long a[500000],ans,x;
    16 
    17 int n;
    18 
    19 int main()
    20 
    21 {
    22 
    23     scanf("%d",&n);
    24 
    25     if (n==1)
    26 
    27     {
    28 
    29         scanf("%I64d",&x);
    30 
    31         printf("%I64d",x);
    32 
    33         return 0;
    34 
    35     }
    36 
    37     for (int i=1;i<=n;++i) scanf("%I64d",&a[i]);
    38 
    39     sort(a+1,a+n+1);
    40 
    41     for (int i=1;i<=n;++i) ans+=(i+1)*a[i];
    42 
    43     ans-=a[n];
    44 
    45     printf("%I64d",ans);
    46 
    47     return 0;
    48 
    49 }
    View Code

    B:Appleman and Tree

    题意:给出一棵树,每个节点有黑色或白色,现在要求删掉一些边后形成的联通块每个块内都恰好有一个黑点,求方案数。

    题解:树形dp

    dp[i][0]表示节点i所在的子树联通块内有0个黑点时的子树内划分方案数

    dp[i][1]表示节点i所在的子树联通块内有1个黑点时的子树内划分方案数

    转移:对于i的一个孩子j

    考虑:dp[i][0]

    若j所在子树联通块也没有黑点,则需要把他和i连起来,要不然永远也不会有黑点。

    若j所在子树联通块内有黑点,则根据状态定义把i和j之间的边删除掉。

    得到:dp[i][0]=dp[i][0]*dp[j][0]+dp[i][0]*dp[j][0]

    考虑:dp[i][1]

    若j所在子树联通块内没有黑点,则需要把他和i连起来,要不然永远也不会有黑点。

    若j所在子树联通块内有黑点:

    ①若i所在联通块有黑点,则把i和j断开

    ②若i所在联通块没有黑点,则把i和j连上

    得到:dp[i][1]=dp[i][1]*dp[j][0]+dp[i][1]*dp[j][1]+dp[i][0]*dp[j][1] 至此问题得到解决。

     1 #include <cstdio>
     2 
     3 #include <iostream>
     4 
     5 #include <cmath>
     6 
     7 #include <cstring>
     8 
     9 #include <algorithm>
    10 
    11 const int mod=1e9+7;
    12 
    13 using namespace std;
    14 
    15 int n,a[100005],x;
    16 
    17 long long dp[100005][5];
    18 
    19 int main()
    20 
    21 {
    22 
    23     memset(dp,0,sizeof(dp));
    24 
    25     scanf("%d",&n);
    26 
    27     for (int i=1;i<n;++i) scanf("%d",&a[i]);
    28 
    29     for (int i=0;i<n;++i)
    30 
    31     {
    32 
    33         scanf("%d",&x);
    34 
    35         dp[i][x]=1;
    36 
    37     }
    38 
    39     for (int i=n-1;i>=1;--i)
    40 
    41     {
    42 
    43         dp[a[i]][1]=(dp[a[i]][1]*(dp[i][0]+dp[i][1])+dp[a[i]][0]*dp[i][1])%mod;
    44 
    45         dp[a[i]][0]=(dp[a[i]][0]*(dp[i][0]+dp[i][1]))%mod;
    46 
    47     }
    48 
    49     printf("%I64d
    ",dp[0][1]);
    50 
    51     return 0;
    52 
    53 }
    View Code

    C:Appleman and a Sheet of Paper

    题解:一个折纸的过程,有两种操作,第一种是把前X单位的纸折到后半部分的上面,第二种为询问长度L到R区间实际上纸的长度为多少,即那一段纸的厚度为多少。

    题意:实际上直接模拟这个过程即可。记录前缀和sum[i]表示到i为止一共有几段纸,然后就是每次模拟这个过程更新sum数组。

       对于折超过一半的处理可以等效成将令一半叠上来,记录一个是否翻转过的标记即可,因为随着折叠纸的长度不断变小,复杂度是可以接受的。

     1 #include <cstdio>
     2 
     3 #include <cmath>
     4 
     5 #include <iostream>
     6 
     7 #include <cstring>
     8 
     9 #include <algorithm>
    10 
    11 
    12 
    13 using namespace std;
    14 
    15 int n,m,dq,rev,last,sum[200000],z,l,r;
    16 
    17 int main()
    18 
    19 {
    20 
    21     scanf("%d%d",&n,&m);
    22 
    23     dq=n;rev=0;last=0;
    24 
    25     for (int i=1;i<=n;++i) sum[i]=i;
    26 
    27     for (int t=1;t<=m;++t)
    28 
    29     {
    30 
    31         scanf("%d",&z);
    32 
    33         if (z==1)
    34 
    35         {
    36 
    37             scanf("%d",&l);
    38 
    39             if (l>dq-l)
    40 
    41             {
    42 
    43                 l=dq-l;
    44 
    45                 rev^=1;
    46 
    47             }
    48 
    49             if (rev) 
    50 
    51             {
    52 
    53                 for (int i=dq-l;i<dq;++i) sum[last+2*(dq-l)-i]+=(n-sum[last+i]);
    54 
    55             }
    56 
    57             else 
    58 
    59             {
    60 
    61                 last+=l;
    62 
    63                 for (int i=0;i<l;++i) sum[last+i]-=sum[last-i];
    64 
    65             }
    66 
    67             dq-=l;
    68 
    69         }
    70 
    71         else
    72 
    73         {
    74 
    75             scanf("%d%d",&l,&r);
    76 
    77             if (rev)
    78 
    79             {
    80 
    81                 int temp=dq-r;
    82 
    83                 r=dq-l;
    84 
    85                 l=temp;
    86 
    87             }
    88 
    89             printf("%d
    ",sum[last+r]-sum[last+l]);
    90 
    91         }
    92 
    93         //for (int i=1;i<=n;++i) cout<<sum[i]<<endl;
    94 
    95     }
    96 
    97     return 0;
    98 
    99 }
    View Code
  • 相关阅读:
    2019 荔枝java面试笔试题 (含面试题解析)
    2019 乐游网络java面试笔试题 (含面试题解析)
    2019 吉比特java面试笔试题 (含面试题解析)
    2019 拉卡拉java面试笔试题 (含面试题解析)
    2019 东方财富网java面试笔试题 (含面试题解析)
    2019 途牛旅游网java面试笔试题 (含面试题解析)
    2019 263云通信java面试笔试题 (含面试题解析)
    2019 贝壳找房java面试笔试题 (含面试题解析)
    偶分频、奇分频、任意整数分频
    PWM呼吸灯
  • 原文地址:https://www.cnblogs.com/zscnash/p/4157274.html
Copyright © 2011-2022 走看看