• Codeforces Round #243


    CF 243  DIV1 & DIV2

    DIV2的A和B都太水,直接暴力搞就可以的。

    DIV2A

     1 /* ***********************************************
     2 Author        :kuangbin
     3 Created Time  :2014/4/30 19:42:51
     4 File Name     :E:2014ACMCodeforcesCF243DIV2_A.cpp
     5 ************************************************ */
     6 
     7 #include <stdio.h>
     8 #include <string.h>
     9 #include <iostream>
    10 #include <algorithm>
    11 #include <vector>
    12 #include <queue>
    13 #include <set>
    14 #include <map>
    15 #include <string>
    16 #include <math.h>
    17 #include <stdlib.h>
    18 #include <time.h>
    19 using namespace std;
    20 
    21 int a[110];
    22 int main()
    23 {
    24     //freopen("in.txt","r",stdin);
    25     //freopen("out.txt","w",stdout);
    26     int n,s;
    27     while(scanf("%d%d",&n,&s) == 2)
    28     {
    29         for(int i = 0;i < n;i++)
    30             scanf("%d",&a[i]);
    31         sort(a,a+n);
    32         int ans = 0;
    33         for(int i = 0;i < n-1;i++)
    34             ans += a[i];
    35         if(ans <= s)printf("YES
    ");
    36         else printf("NO
    ");
    37     }
    38     return 0;
    39 }
    View Code

    DIV2B

     1 /* ***********************************************
     2 Author        :kuangbin
     3 Created Time  :2014/4/30 19:53:16
     4 File Name     :E:2014ACMCodeforcesCF243DIV2_B.cpp
     5 ************************************************ */
     6 
     7 #include <stdio.h>
     8 #include <string.h>
     9 #include <iostream>
    10 #include <algorithm>
    11 #include <vector>
    12 #include <queue>
    13 #include <set>
    14 #include <map>
    15 #include <string>
    16 #include <math.h>
    17 #include <stdlib.h>
    18 #include <time.h>
    19 using namespace std;
    20 const int MAXN = 110;
    21 int a[MAXN][MAXN];
    22 int b[MAXN][MAXN];
    23 
    24 int main()
    25 {
    26     //freopen("in.txt","r",stdin);
    27     //freopen("out.txt","w",stdout);
    28     int n,m;
    29     while(scanf("%d%d",&n,&m) == 2)
    30     {
    31         for(int i = 0;i < n;i++)
    32             for(int j = 0;j < m;j++)
    33                 scanf("%d",&a[i][j]);
    34         int tmp = n;
    35         if(tmp%2)
    36         {
    37             printf("%d
    ",n);
    38             continue;
    39         }
    40         for(int i = 0;i < n;i++)
    41             for(int j = i+1;j < n;j++)
    42             {
    43                 int tt = 1;
    44                 for(int k = 0;k < m;k++)
    45                     if(a[i][k] != a[j][k])
    46                     {
    47                         tt = 0;
    48                         break;
    49                     }
    50                 b[i][j] = b[j][i] = tt;
    51             }
    52         for(int t = 1;t <= n;t++)
    53         {
    54             int tmp = t;
    55             while(tmp < n)tmp *= 2;
    56             if(tmp != n)continue;
    57             bool flag = true;
    58             int mir = t;
    59             while(mir != n)
    60             {
    61                 for(int i = 0;i < mir;i++)
    62                     if(b[i][2*mir-1-i] == 0)
    63                     {
    64                         flag = false;
    65                         break;
    66                     }
    67                 if(!flag)break;
    68                 mir *= 2;
    69             }
    70             if(flag)
    71             {
    72                 printf("%d
    ",t);
    73                 break;
    74             }
    75         }
    76     }
    77     return 0;
    78 }
    View Code

    DIV1A

    题意:

    给出了n(1<=n<=200)的数列a, 让你最多交换k(1<=k<=10)次,使得最大连续子序列的和最大。输出最大的连续子序列和。

    因为n比较小,直接暴力枚举区间,然后将这个区间的k个小的,换成比较大的。

    代码君:

     1 /* ***********************************************
     2 Author        :kuangbin
     3 Created Time  :2014/4/27 23:29:36
     4 File Name     :E:2014ACMCodeforcesCF243A.cpp
     5 ************************************************ */
     6 
     7 #include <stdio.h>
     8 #include <string.h>
     9 #include <iostream>
    10 #include <algorithm>
    11 #include <vector>
    12 #include <queue>
    13 #include <set>
    14 #include <map>
    15 #include <string>
    16 #include <math.h>
    17 #include <stdlib.h>
    18 #include <time.h>
    19 using namespace std;
    20 
    21 const int MAXN = 220;
    22 int a[MAXN];
    23 int b[MAXN];
    24 int c[MAXN];
    25 int main()
    26 {
    27     //freopen("in.txt","r",stdin);
    28     //freopen("out.txt","w",stdout);
    29     int n,k;
    30     while(scanf("%d%d",&n,&k) == 2)
    31     {
    32         for(int i = 1;i <= n;i++)
    33             scanf("%d",&a[i]);
    34         int ans = -1000000000;
    35         for(int l = 1;l <= n;l++)
    36             for(int r = l;r<= n;r++)
    37             {
    38                 int cnt1 = 0;
    39                 int cnt2 = 0;
    40                 for(int i = 1;i <= n;i++)
    41                 {
    42                     if(i >= l && i <= r)
    43                         b[cnt1++] = a[i];
    44                     else c[cnt2++] = a[i];
    45                 }
    46                 sort(b,b+cnt1);
    47                 sort(c,c+cnt2);
    48                 reverse(c,c+cnt2);
    49                 int tt = min(cnt1,cnt2);
    50                 tt = min(tt,k);
    51                 for(int i = 1;i < cnt1;i++)
    52                     b[i] += b[i-1];
    53                 for(int i = 1;i < cnt2;i++)
    54                     c[i] += c[i-1];
    55                 
    56 
    57                 for(int i = 0;i <= tt;i++)
    58                 {
    59                     int num1 = i;
    60                     int num2 = i;
    61                     int tmp = b[cnt1-1];
    62                     if(num1 > 0)tmp -= b[num1-1];
    63                     if(num2 > 0)tmp += c[num2-1];
    64                     ans = max(ans,tmp);
    65                 }
    66 
    67             }
    68         printf("%d
    ",ans);
    69     }
    70     return 0;
    71 }
    View Code

    DIV1B

    给出一个n*m的01矩阵, 让你最多改变k个里面的值(0变1,1变0), 使得0、1的连通分量是矩阵。输出最少步数

    1 ≤ n, m ≤ 100; 1 ≤ k ≤ 10

    题解:

    如果01连通分量是矩形,

    那么矩形一定是这样的:

    0101010

    1010101

    0101010

    1010101

    (上面的01代表子矩阵块)。

    也就是每一行要么是相同,要么是相反的。

    如果n>k, 肯定有一行是不能改变的,那么枚举这一行,然后其余的要么变相同,要么变相反,看最少的步数。

    如果n<k ,那么可以枚举第一列的状态(2^k), 然后其余列变成和第一列相同或者相反。

     1 /* ***********************************************
     2 Author        :kuangbin
     3 Created Time  :2014/4/29 11:30:04
     4 File Name     :E:2014ACMCodeforcesCF243B.cpp
     5 ************************************************ */
     6 
     7 #include <stdio.h>
     8 #include <string.h>
     9 #include <iostream>
    10 #include <algorithm>
    11 #include <vector>
    12 #include <queue>
    13 #include <set>
    14 #include <map>
    15 #include <string>
    16 #include <math.h>
    17 #include <stdlib.h>
    18 #include <time.h>
    19 using namespace std;
    20 const int MAXN = 110;
    21 int a[MAXN][MAXN];
    22 
    23 int main()
    24 {
    25     //freopen("in.txt","r",stdin);
    26     //freopen("out.txt","w",stdout);
    27     int n,m,k;
    28     while(scanf("%d%d%d",&n,&m,&k) == 3)
    29     {
    30         for(int i = 0;i < n;i++)
    31             for(int j = 0;j < m;j++)
    32                 scanf("%d",&a[i][j]);
    33         int ans = 100000000;
    34         if(n > k)
    35         {
    36             for(int t = 0;t < n;t++)
    37             {
    38                 int tmp = 0;
    39                 for(int i = 0;i < n;i++)
    40                 {
    41                     int cnt = 0;
    42                     for(int j = 0;j < m;j++)
    43                         if(a[i][j] == a[t][j])
    44                             cnt++;
    45                     tmp += min(cnt,m-cnt);
    46                 }
    47                 ans = min(tmp,ans);
    48             }
    49         }
    50         else
    51         {
    52             for(int t = 0;t < (1<<n);t++)
    53             {
    54                 int tmp = 0;
    55                 for(int j = 0;j < m;j++)
    56                 {
    57                     int cnt = 0;
    58                     for(int i = 0;i < n;i++)
    59                         if(a[i][j] == ((t>>i)&1))
    60                             cnt++;
    61                     tmp += min(cnt,n-cnt);
    62                 }
    63                 ans = min(tmp,ans);
    64             }
    65         }
    66         if(ans <= k)printf("%d
    ",ans);
    67         else printf("-1
    ");
    68     }
    69     return 0;
    70 }
    View Code

    DIV1C

    题意:比较长,自己看题目吧

    1 ≤ s ≤ 3·10^5; 10^3 ≤ e ≤ 10^4

    所以第一个操作最多是300次.

    用dp[i][j] 表示a序列消掉了前i个,消了j次,b序列的最小位置。

    转移的时候,dp[i][j], 其实就是dp[0][j-1],dp[1][j-1],......dp[i-1][j-1]中最小的,下一个a[i]的位置。

    用个数组标记下位置,因为那个最小值是递减的。

     1 /* ***********************************************
     2 Author        :kuangbin
     3 Created Time  :2014/4/29 22:16:58
     4 File Name     :E:2014ACMCodeforcesCF243C.cpp
     5 ************************************************ */
     6 
     7 #include <stdio.h>
     8 #include <string.h>
     9 #include <iostream>
    10 #include <algorithm>
    11 #include <vector>
    12 #include <queue>
    13 #include <set>
    14 #include <map>
    15 #include <string>
    16 #include <math.h>
    17 #include <stdlib.h>
    18 #include <time.h>
    19 using namespace std;
    20 
    21 int dp[310][100010];
    22 int a[100010];
    23 int b[100010];
    24 vector<int>vb[100010];
    25 int next[100010];
    26 
    27 int main()
    28 {
    29     //freopen("in.txt","r",stdin);
    30     //freopen("out.txt","w",stdout);
    31     int n,m,s,e;
    32     while(scanf("%d%d%d%d",&n,&m,&s,&e) == 4)
    33     {
    34         for(int i = 0;i < n;i++)
    35             scanf("%d",&a[i]);
    36         for(int i = 0;i < m;i++)
    37             scanf("%d",&b[i]);
    38         for(int i = 1; i <= 100000;i++)
    39             vb[i].clear();
    40         for(int i = 0;i < m;i++)
    41             vb[b[i]].push_back(i);
    42         for(int i = 1; i <= 100000;i++)
    43             vb[i].push_back(m);
    44         int k = s/e;
    45         int ans = 0;
    46         for(int i = 1;i <= k;i++)
    47         {
    48             for(int j = 1;j <= 100000;j++)
    49                 next[j] = vb[j].size() - 1;
    50             int mm = m;
    51             if(i == 1)mm = -1;
    52             for(int j = 0;j < n;j++)
    53             {
    54                 while(next[a[j]] > 0 && vb[a[j]][next[a[j]]-1] > mm)
    55                     next[a[j]]--;
    56                 dp[i][j] = vb[a[j]][next[a[j]]];
    57                 if(i > 1)mm = min(mm,dp[i-1][j]);
    58                 if(dp[i][j] < m && j + dp[i][j] + 2 + e*i <= s)
    59                     ans = max(ans,i);
    60             }
    61         }
    62         printf("%d
    ",ans);
    63     }
    64     return 0;
    65 }
    View Code

    DIV1D

    题意,给了n个点, 让你求出有多少个平行于坐标轴的正方形,四个点都在给定的点上。

    可以使用hash或者二分查找,快速判断一个点是不是存在。

    枚举x坐标,如果x的个数<sqrt(n),  那么两重循环枚举这个x的点,确定边长,然后进行hash判断是不是存在。

    如果x的个数>=sqrt(n), 那么枚举下所有的点,来确定下边长,然后进行hash判断

     1 /* ***********************************************
     2 Author        :kuangbin
     3 Created Time  :2014/4/30 18:27:57
     4 File Name     :E:2014ACMCodeforcesCF243D.cpp
     5 ************************************************ */
     6 
     7 #include <stdio.h>
     8 #include <string.h>
     9 #include <iostream>
    10 #include <algorithm>
    11 #include <vector>
    12 #include <queue>
    13 #include <set>
    14 #include <map>
    15 #include <string>
    16 #include <math.h>
    17 #include <stdlib.h>
    18 #include <time.h>
    19 using namespace std;
    20 
    21 vector<int>vx[100010];
    22 bool has(int x,int y)
    23 {
    24     if(x > 100000 || y > 100000 || x < 0 || y < 0)return false;
    25     return binary_search(vx[x].begin(),vx[x].end(),y);
    26 }
    27 int main()
    28 {
    29     //freopen("in.txt","r",stdin);
    30     //freopen("out.txt","w",stdout);
    31     int n;
    32     while(scanf("%d",&n) == 1)
    33     {
    34         for(int i = 0;i <= 100000;i++)
    35             vx[i].clear();
    36         int x,y;
    37         for(int i = 0;i < n;i++)
    38         {
    39             scanf("%d%d",&x,&y);
    40             vx[x].push_back(y);
    41         }
    42         for(int i = 0;i <= 100000;i++)
    43             sort(vx[i].begin(),vx[i].end());
    44         int ans = 0;
    45         int bd = (int)sqrt(1.0*n);
    46         for(int x = 0;x <= 100000;x++)
    47             if(vx[x].size())
    48             {
    49                 if(vx[x].size() < bd)
    50                 {
    51                     for(int i = 0;i < vx[x].size();i++)
    52                         for(int j = i+1;j < vx[x].size();j++)
    53                         {
    54                             int d = vx[x][j] - vx[x][i];
    55                             if(has(x+d,vx[x][i]) && has(x+d,vx[x][j]))
    56                                 ans++;
    57                         }
    58                 }
    59                 else
    60                 {
    61                     for(int xx = x+1;xx <= 100000;xx++)
    62                         for(int i = 0;i < vx[xx].size();i++)
    63                         {
    64                             int yy = vx[xx][i];
    65                             int d = xx - x;
    66                             if(has(x,yy) && has(x,yy+d) && has(xx,yy+d))
    67                                 ans++;
    68                         }
    69                 }
    70             }
    71         printf("%d
    ",ans);
    72     }
    73     return 0;
    74 }
    View Code

    DIV1E

    经典的DP题

    使用dp[i][j] 表示最多j个不相交区间,最靠左的j个不相交区间的最后一个区间位置是i.

    如果dp[i][j] -> dp[ii][j+1]的话,2^( (ii-i)*i ) 这种是横跨的区间,可选可不选。

    (ii-i)个区间是最少要选择一个的,  2^(ii-i)-1

    然后就可以得出来了。

     1 /* ***********************************************
     2 Author        :kuangbin
     3 Created Time  :2014/4/28 0:47:23
     4 File Name     :E:2014ACMCodeforcesCF243E.cpp
     5 ************************************************ */
     6 
     7 #include <stdio.h>
     8 #include <string.h>
     9 #include <iostream>
    10 #include <algorithm>
    11 #include <vector>
    12 #include <queue>
    13 #include <set>
    14 #include <map>
    15 #include <string>
    16 #include <math.h>
    17 #include <stdlib.h>
    18 #include <time.h>
    19 using namespace std;
    20 const int MOD = 1e9+7;
    21 const int MAXN = 550;
    22 int dp[MAXN][MAXN];//dp[i][j]表示有j个不相交区间,最左的最后一个区间的位置是i
    23 void Add(int &a,int b)
    24 {
    25     a += b;
    26     while(a >= MOD)a -= MOD;
    27 }
    28 int two[510*510];
    29 int main()
    30 {
    31     //freopen("in.txt","r",stdin);
    32     //freopen("out.txt","w",stdout);
    33     int n,k;
    34     two[0] = 1;
    35     for(int i = 1;i <= 500*500;i++)
    36         two[i] = 2*two[i-1]%MOD;
    37     while(scanf("%d%d",&n,&k) == 2)
    38     {
    39         memset(dp,0,sizeof(dp));
    40         dp[0][0] = 1;
    41         for(int i = 0;i < n;i++)
    42             for(int j = 0;j < k;j++)
    43                 if(dp[i][j])
    44                 {
    45                     for(int ii = i+1;ii <= n;ii++)
    46                     {
    47                         long long tmp = two[i*(ii - i)];
    48                         tmp = tmp*(two[ii-i]-1)%MOD;
    49                         Add(dp[ii][j+1],tmp*dp[i][j]%MOD);
    50                     }
    51                 }
    52         int ans = 0;
    53         for(int i = 0;i <= n;i++)
    54             Add(ans,(long long)dp[i][k]*two[i*(n-i)]%MOD);
    55         printf("%d
    ",ans);
    56     }
    57     return 0;
    58 }
    View Code
  • 相关阅读:
    xpath 笔记
    实验四 决策树算法及应用
    实验三 朴素贝叶斯算法及应用
    机器学习 实验二 K-近邻算法及应用
    实验一 感知器及其应用
    JAVA学习路线
    实验三 面向对象分析与设计
    实验二 结构化分析与设计
    实验1:软件开发文档与工具的安装与使用
    ATM管理系统
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3702113.html
Copyright © 2020-2023  润新知