2016-2017 ACM-ICPC CHINA-Final (慢慢做慢慢更新)

本文提供了三道编程竞赛题目的解答思路及代码实现:Problem A利用简单数论解决;Problem D采用二分加贪心策略;Problem L通过模拟比赛过程得出结论。
用力戳我下载全套题的pdf~

用力戳我直达cf评测系统~

目前已做出:

Problem A. Number Theory Problem

Problem D. Ice Cream Tower

Problem L. World Cup

题解:

A。简单数论

1
2
3
4
5
6
7
8
9
10
11
12
#include <bits/stdc++.h>
using  namespace  std;
int  main()
{
     int  t, n, Case;
     scanf ( "%d" ,&t);
     for (Case = 1; Case <= t; Case++)
     {
         scanf ( "%d" ,&n);
         printf ( "Case #%d: %d\n" ,Case, n / 3);
     }
}

D。二分 + 贪心

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <bits/stdc++.h>
typedef  long  long  ll;
using  namespace  std;
ll a[300030];
ll tp[300030]; //judge时用
int  t, n ,k;
bool  judge( int  x)
{
     memset (tp,-1, sizeof (tp));
     for ( int  i = 0; i < x; i++)
         tp[i] = a[i];
     int  pos = x;
     for ( int  i = 2; i <= k; i++)  //层数
     {
         for ( int  j = 0; j < x; j++)  //每一层有 x 个
         {
             pos = lower_bound(a + pos, a + n, tp[j] * 2) - a;
             if (pos + 1 > n)
                 return  false ;
             tp[j] = a[pos];  //更新当前最底层
             pos++;  //下一次 从 下一个数开始搜
         }
     }
     return  true //叠加成功则返回true
}
int  main()
{
     int  Case;
     scanf ( "%d" ,&t);
     for (Case = 1; Case <= t; Case++)
     {
         memset (a,0, sizeof (a));
         scanf ( "%d%d" ,&n, &k);
         for ( int  i = 0; i < n; i++)
             scanf ( "%I64d" ,a + i);
         sort(a, a + n);
         int  low = 0, high = n / k, mid;
         while (low < high)
         {
             int  mid = (low + high + 1) >> 1;
             if (judge(mid))
                 low = mid;  //搜右界
             else
                 high = mid - 1;
         }
         printf ( "Case #%d: %d\n" ,Case, low);
     }
}

L。模拟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <bits/stdc++.h>
#define MEM(a,b) memset(a,b,sizeof(a))
using  namespace  std;
int  sco[12][12][12][12];
void  init()
{
     MEM(sco,0);
     int  op1[]={3,1,0};  // a a a b b c
     int  op2[]={0,1,3};  // b c d c d d
     //枚举六场比赛
     for ( int  k1 = 0; k1 <= 2; k1++)
     for ( int  k2 = 0; k2 <= 2; k2++)
     for ( int  k3 = 0; k3 <= 2; k3++)
     for ( int  k4 = 0; k4 <= 2; k4++)
     for ( int  k5 = 0; k5 <= 2; k5++)
     for ( int  k6 = 0; k6 <= 2; k6++)
     {
         //根据op1 op2的注释统计分值
         int  A = op1[k1] + op1[k2] + op1[k3];
         int  B = op2[k1] + op1[k4] + op1[k5];
         int  C = op2[k2] + op2[k4] + op1[k6];
         int  D = op2[k3] + op2[k5] + op2[k6];
         sco[A][B][C][D] ++;   //累计最终榜单
     }
}
int  main()
{
     int  n, a, b, c, d;
     init();   //只需要暴力跑一次就行
     scanf ( "%d" ,&n);
     for ( int  Case = 1; Case <= n; Case++)
     {
         scanf ( "%d%d%d%d" ,&a, &b, &c, &d);
         if (sco[a][b][c][d] == 0)
             printf ( "Case #%d: Wrong Scoreboard\n" ,Case);
         else  if (sco[a][b][c][d] == 1)
             printf ( "Case #%d: Yes\n" ,Case);
         else
             printf ( "Case #%d: No\n" ,Case);
     }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值