2017-2018 ACM-ICPC Asia East Continent League Final (ECL-Final 2017) Solution

A:Chat Group

题意:给出一个n, k 计算C(n, k) -> C(n,n) 的和

思路:k只有1e5 反过来想,用总的(2^ n) 减去 C(n, 0) -> C(n, k - 1), 预处理逆元,

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define ll long long
 6 #define N 100010
 7 
 8 const ll MOD = (ll)1e9 + 7;
 9 
10 int t;
11 ll n, k;
12 ll inv[N];
13 
14 inline void Init()
15 {
16     inv[1] = 1;
17     for (int i = 2; i < N; ++i) inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
18 }
19 
20 inline ll qpow(ll x, ll n)
21 {
22     ll base = x;
23     ll ans = 1;
24     while (n)
25     {
26         if (n & 1) ans = (ans * base) % MOD;
27         base = base * base % MOD;
28         n >>= 1;
29     }
30     return ans;
31 }
32 
33 int main()
34 {
35     Init();
36     scanf("%d", &t);
37     for (int kase = 1; kase <= t; ++kase)
38     {
39         scanf("%lld%lld", &n, &k);
40         printf("Case #%d: ", kase);
41         if (k > n)
42         {
43             puts("0");
44             continue;
45         }
46         ll ans = qpow(2, n);
47         ll tmp = 1;
48         for (int i = 0; i < k; ++i)
49         {
50             ans = (ans - tmp + MOD) % MOD;
51             tmp = tmp *  (n - i) % MOD * inv[i + 1] % MOD;
52         }
53         printf("%lld\n", ans);
54     }
55     return 0;
56 }
View Code

 

B:Scapegoat

题意: 给出n件错误,每件错误的严重程度是ai, 有m只替罪羊,每只替罪羊只能承担一件事情的责任,如果多只替罪羊承担一件事情的责任,那么就是这多只替罪羊平均分担这件事情的责任,求每只替罪羊承担责任的方差

思路:当替罪羊总量固定的时候,那么平均值也是固定的,那么我们可以根据减少量排序,每次贪心取最大

 1 #include <bits/stdc++.h>
 2 using namespace std; 
 3 
 4 #define N 200010
 5 
 6 double ave;
 7 
 8 struct node
 9 {
10     int num;
11     double tot, cur, dis, gap; 
12     inline bool operator < (const node &r) const
13     {
14         return gap < r.gap;
15     }
16     inline node() {}
17     inline node(double _tot, int _num, double _cur)
18     {
19         tot = _tot; num = _num; cur = _cur;
20         dis = (cur - ave) * (cur - ave) * num;
21         gap = dis - ((tot / (num + 1) - ave) * (tot / (num + 1) - ave)) * (num + 1);
22     }
23 };
24 
25 int t, n, m;
26 double arr[N];
27 
28 inline void Run()
29 {    
30     scanf("%d", &t);
31     for (int kase = 1; kase <= t; ++kase)
32     {
33         printf("Case #%d: ", kase);
34         scanf("%d%d", &n, &m);
35         ave = 0;
36         for (int i = 1; i <= n; ++i) scanf("%lf", arr + i), ave += arr[i]; ave /= m;
37         priority_queue <node> q; 
38         for (int i = 1; i <= n; ++i)
39             q.emplace(arr[i], 1, arr[i]);
40         for (int i = n + 1; i <= m; ++i)
41         {
42             node top = q.top(); q.pop();
43             q.emplace(top.tot, top.num + 1, top.tot / (top.num + 1));
44         }
45         double ans = 0;
46         for (int i = 1; i <= n; ++i)
47         {
48             node top = q.top(); q.pop();
49             ans += top.dis; 
50         }
51         ans /= m;
52         printf("%.10f\n", ans);
53     }
54 }
55 
56 int main()
57 {
58     #ifdef LOCAL
59         freopen("Test.in", "r", stdin);
60     #endif
61 
62     Run();
63     
64     return 0;
65 }
View Code

 

 

C:Traffic Light

题意:给出两个红绿灯之间的时间以及每个红绿灯的红扥和绿灯时间,求最小的最坏情况。

思路:当经过一个红灯的时候可以发现,可以通过调整OFFi来保证接下来都是绿灯,所以答案就是最大的红灯时间和路程

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define N 1010
 6 
 7 double sum;
 8 int n;
 9 
10 int main()
11 {
12     int t;
13     scanf("%d", &t);
14     for(int cas = 1; cas <= t; ++cas)
15     {
16         scanf("%d", &n);
17         sum = 0;
18         for(int i = 0; i <= n; ++i)
19         {
20             double x;
21             scanf("%lf", &x);
22             sum += x;
23         }
24         double tmp = 0;
25         for(int i = 1; i <= n; ++i)
26         {
27             double a, b;
28             scanf("%lf %lf", &a, &b);
29             tmp = max(tmp, b);
30         }
31         sum += tmp;
32         printf("Case #%d: %.10f\n", cas, sum);
33     }
34     return 0;
35 }
View Code

 

D:Mr. Panda and Geometric Sequence

留坑。

 

E:Snakebird

留坑。

 

F:Good Number

留坑。

 

G:Image Recognition

留坑。

 

H:Mr. Panda and Birthday Song

留坑。

 

I:PLAYERUNKNOWN'S BATTLEGROUNDS

留坑。

 

J:Straight Master

题意:给出n种牌的数量,你可以打出长度为3,4,5的顺子,问最后能否打完。

思路:345可以拼凑出所有大于等于3的数字。先构造出差分约束,将每一个正值贪心的与最近的负值匹配,贪心扫一遍即可

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 2e5 + 10;
 6 
 7 int n;
 8 int arr[maxn];
 9 int brr[maxn];
10 
11 int main()
12 {
13     int t;
14     scanf("%d", &t);
15     for (int cas = 1; cas <= t; ++cas)
16     {
17         scanf("%d", &n);
18         for (int i = 1; i <= n; ++i)
19         {
20             scanf("%d", arr + i);
21         }
22         arr[n + 1] = 0;
23         for (int i = 1; i <= n + 1; ++i)
24         {
25             brr[i] = arr[i] - arr[i - 1];
26         }
27         bool flag = true;
28         int now = 0;
29         for (int i = 1; i <= n + 1; ++i)
30         {
31             while (brr[i] < 0 && now <= i - 3)
32             {
33                 if (brr[now] + brr[i] >= 0)
34                 {
35                     brr[now] += brr[i];
36                     brr[i] = 0;
37                 }
38                 else
39                 {
40                     brr[i] += brr[now];
41                     brr[now] = 0;
42                 }
43                 if (brr[i] < 0) ++now;
44             }
45             if (brr[i] < 0)
46             {
47                 flag = false;
48                 break;
49             }
50         }
51         printf("Case #%d: %s\n", cas, flag ? "Yes" : "No");
52     }
53     return 0;
54 }
View Code

 

 

K:Downgrade

题意:给出一个游戏里面,有主等级以及副等级,如果有一天没有打,那么它的等级就将主等级当成副等级,副等级满了可以生主等级

思路:虽然n很大,然后a只有1e5,可以知道最多下降到1-1就不会再变,然后二分找对应的主等级

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int N = 100000+10;
 6 long long la[N],f[N];
 7 int main() {
 8     long long t,p,i,j,l,r,k;
 9     long long a,b,x,y,n,m;
10     scanf("%lld",&t);
11     p=0;
12     f[0]=0;
13     while (t--) {
14         ++p;
15         scanf("%lld%lld%lld",&a,&b,&n); 
16         for (i=1;i<=a;++i) {
17             scanf("%lld",&la[i]);
18             f[i]=f[i-1]+la[i];
19         }
20         x=a; y=b; 
21         while (n--)
22         {
23             long long prex = x,prey = y;
24             int pos = lower_bound(f + 1, f + 1 + a, x) - f;
25             y = x - f[pos - 1]; x = pos;
26             if(x == prex && y == prey) break;
27             if(x == 1 && y == 1) break;
28         }
29         printf("Case #%lld: %lld-%lld\n",p,x,y);
30     }
31     return 0;
32 }
View Code

 

L:SOS

题意:给出n个格子,两个人轮流放'S' 或者 'O' 如果一个人放了之后,棋盘上出现"SOS" 它就赢了,Panda先手,求胜负关系或者平局

思路:有一个规律,当出现S__S 这样的局面的时候,谁第一步走进这个坑,谁就输了

找一下规律,16(lts)是一个分界点

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int t, n;
 6 
 7 int main()
 8 {
 9     scanf("%d", &t);
10     int d = 16;
11     for (int kase = 1; kase <= t; ++kase)
12     {
13         printf("Case #%d: ", kase);
14         scanf("%d", &n);
15         if (n < 7)
16             puts("Draw");
17         else if (n < d)
18             puts((n & 1) ? "Panda" : "Draw");
19         else
20             puts((n & 1) ? "Panda" : "Sheep");
21     }
22     return 0;
23 }
View Code

 

M:World Cup

水。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define ll long long
 6 
 7 int t, n;
 8 ll price[10];
 9 
10 int main()
11 {
12     scanf("%d", &t);
13     for (int kase = 1; kase <= t; ++kase)
14     {
15         for (int i = 1; i <= 5; ++i) scanf("%lld", price + i);
16         scanf("%d", &n);
17         ll ans = 0;
18         for (int i = 1, num; i <= n; ++i)
19         {
20             scanf("%d", &num);
21             if (num >= 1 && num <= 48) ans += price[1];
22             else if (num >= 49 && num <= 56) ans += price[2];
23             else if (num >= 57 && num <= 60) ans += price[3];
24             else if (num >= 61 && num <= 62) ans += price[4];
25             else ans += price[5];
26         }    
27         printf("Case #%d: %lld\n", kase, ans * 10000);
28     }
29     return 0;
30 }
View Code

 

posted @ 2018-08-21 16:55  Dup4  阅读(1297)  评论(0编辑  收藏  举报