2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017) Solution

A:Concertsnode

題意:給出一個串T, 一個串S,求串S中有多少個串T,能夠重複,可是兩個字符間的距離要知足給出的數據要求ios

思路:先順序統計第一個T中的字符在S中有多少個,而後對於第二位的以及後面的,咱們從後面往前推,前綴和搞一搞,注意間距c++

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define N 100010
 6 
 7 typedef long long ll;
 8 
 9 const int MOD = 1e9 + 7;
10 
11 ll sum[N];
12 
13 char strN[N], strK[N];
14 
15 int n,k;
16 int pos[100];
17 
18 int main()
19 {
20     while(~scanf("%d %d",&k,&n))
21     {
22         memset(sum, 0, sizeof sum);
23         for(int i = 0; i < 26; ++i)
24         {
25             scanf("%d",&pos[i]);
26         }
27         scanf("%s",strK + 1);
28         scanf("%s",strN + 1);
29         for(int i = 1;i <= n; ++i)
30         {
31             sum[i] = (strN[i] == strK[1]) + sum[i - 1];
32             sum[i] %= MOD;
33         }
34         for(int i = 2; i <= k; ++i)
35         {
36             for(int j = n; j >= 1; --j)
37             {
38                 if(strN[j] == strK[i])
39                 {
40                     int idx = strK[i - 1] - 'A';
41                     idx = pos[idx];
42                     if(j - idx - 1 < 1) sum[j] = 0;
43                     else sum[j] = sum[j - idx - 1];
44                 }
45                 else sum[j] = 0;
46             }
47             for(int j = 1;j <= n; ++j)
48             {
49                 sum[j] += sum[j - 1];
50                 sum[j] %= MOD;
51             }
52         }
53         printf("%lld\n",sum[n]);
54     }
55     return 0;
56 }
View Code

 

B:Brickside

留坑。oop

 

C:Christmas Treespa

留坑。code

 

D:Harry Potter and The Vector Spellorm

題意:給出n個向量,每一個向量有m維,n個向量中有且只有兩維上是一,而後重載了加號運算符和乘號運算符,求最多的非線性相關的向量個數blog

思路:由於每一個向量中有且只有兩個1,那麼能夠想象答案最大確定是m - 1 由於分佈確定是這樣的排序

 

那麼咱們考慮將每一個向量的兩個1連一條邊,那麼每一個連通塊對答案的貢獻就是 連通塊裏面的點數減1

 1 #pragma comment(linker, "/STACK:1024000000,1024000000") 
 2 
 3 #include <bits/stdc++.h>
 4 using namespace std;
 5 
 6 #define INF 0x3f3f3f3f
 7 #define INFLL 0x3f3f3f3f3f3f3f3f
 8 #define ll long long 
 9 #define N 100100
10 
11 int m, n;
12 int pre[N];
13 int arr[N];
14 
15 inline int find(int x)
16 {
17     if (x != pre[x])
18         pre[x] = find(pre[x]);
19     return pre[x];
20 }
21 
22 inline void join(int x, int y)
23 {
24     int fx = find(x), fy = find(y);
25     if (fx != fy)
26         pre[fx] = fy;
27 }
28 
29 inline void Run()
30 {
31     while (scanf("%d%d", &m, &n) != EOF)
32     {
33         memset(arr, 0, sizeof arr);
34         for (int i = 1; i <= m; ++i)
35             pre[i] = i;
36         for (int i = 1, tot, x; i <= m; ++i)
37         {
38             scanf("%d", &tot);
39             while (tot--)
40             {
41                 scanf("%d", &x);
42                 if (arr[x])
43                     join(arr[x], i);
44                 else
45                     arr[x] = i;
46             }
47         }
48         int cnt = 0;
49         for (int i = 1; i <= m; ++i)
50             if (pre[i] == i) ++cnt;
51         printf("%d\n", m - cnt);
52     }
53 }
54 
55 int main()
56 {
57     #ifdef LOCAL
58         freopen("Test.in", "r", stdin);
59     #endif
60 
61     Run();
62     
63     return 0;
64 }
View Code

 

 

E:Looping Playlist

留坑。

 

F:Binary Transformations

題意:給出兩個01串,每位有一個權值,而後要從a串變成b串,每換一次的花費是變以後a串中裏面每一位是1的對應的權值和,求最小花費

思路:貪心的想法

先把1變成0,按權值大小從大到小變,把0變成1,按權值從小到大變

存在一個問題,若是原本a對應的那位以及b對應的那位都是1,可是那位權值特別特別大,能夠將它先變成0,最後再變回來,可能會使得花費更少

容易知道,若是將a裏面全部爲1位的權值從大到小排序,那麼若是存在這樣的方案使得花費減小,那麼確定是一段連續的,枚舉長度,

時間複雜度O(n ^ 2)

注意隨手剪枝

 

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 typedef long long ll;
  6 #define N 5010
  7 const ll INFLL = 0x3f3f3f3f3f3f3f3f;
  8 struct node{
  9     int pos;
 10     int cost;
 11     inline node(){}
 12     inline node(int pos,int cost) :pos(pos), cost(cost){}
 13     inline bool operator < (const node &b) const
 14     {
 15         return cost > b.cost;
 16     }
 17 };
 18 
 19 inline bool cmp1(node a, node b)
 20 {
 21     return a.cost > b.cost;
 22 }
 23 
 24 inline bool cmp2(node a, node b)
 25 {
 26     return a.cost < b.cost;
 27 }
 28 
 29 int n;
 30 ll sum;
 31 int cost[N];
 32 char s1[N];
 33 char s2[N];
 34 
 35 int main()
 36 {
 37     while(~scanf("%d",&n))
 38     {
 39         for(int i = 1; i <= n; ++i)
 40         {
 41             scanf("%d", &cost[i]);
 42         }
 43         sum = 0;
 44         scanf("%s", s1 + 1);
 45         scanf("%s", s2 + 1);
 46         vector<node>ONE, ZERO_ONE;
 47         for(int i = 1; i <= n; ++i)
 48         {
 49             if(s1[i] == '1')
 50             {
 51                 ONE.push_back(node(i, cost[i]));
 52                 sum += cost[i];
 53             }
 54             else if(s1[i] == '0' && s2[i] == '1')
 55             {
 56                 ZERO_ONE.push_back(node(i, cost[i]));
 57             }
 58         }
 59         sort(ONE.begin(), ONE.end(), cmp1);
 60         int len = ONE.size();
 61         ll Begin = sum;
 62         ll ans = INFLL;
 63         for(int sz = -1; sz < len; ++sz)
 64         {
 65             ll tmp = 0;
 66             sum = Begin;
 67             for(int i = 0; i <= sz; ++i)
 68             {
 69                 sum -= ONE[i].cost;
 70                 tmp += sum;
 71                 if(tmp >= ans) break;
 72             }
 73             if(tmp >= ans) continue;
 74             for(int i = sz + 1; i < len; ++i)
 75             {
 76                 int p = ONE[i].pos;
 77                 if(s2[p] == '0')
 78                 {
 79                     sum -= ONE[i].cost;
 80                     tmp += sum;
 81                     if(tmp >= ans) break;
 82                 }
 83             }
 84             if(tmp >= ans) continue;
 85             vector<node>CHANGE = ZERO_ONE;
 86             for(int i = 0; i <= sz; ++i)
 87             {
 88                 int p = ONE[i].pos;
 89                 if(s1[p] == '1' && s2[p] == '1')
 90                 {
 91                     CHANGE.push_back(node(p, cost[p]));
 92                 }
 93             }
 94             sort(CHANGE.begin(), CHANGE.end(), cmp2);
 95             for(int i = 0, lenn = CHANGE.size(); i < lenn; ++i)
 96             {
 97                 sum += CHANGE[i].cost;
 98                 tmp += sum;
 99                 if(tmp >= ans) break;
100             }
101             ans = min(ans, tmp);
102         }
103         printf("%lld\n",ans);
104     }
105     return 0;
106 }
View Code

 

G:Robots

題意:給出n組數據,每組數據包含一個加速度和時間,求按順序獲得的距離,以及按最優順序獲得距離的不一樣

思路:先遍歷一遍算一下,而後貪心按加速度排一下,算一下,算差距

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define N 10010
 6 
 7 struct node
 8 {
 9     double a, s;
10     inline void scan()
11     {
12         scanf("%lf%lf", &a, &s);
13     }
14     inline bool operator < (const node &r) const
15     {
16         return a  > r.a;
17     }
18 }arr[N];
19 
20 int n;
21 
22 inline double work()
23 {
24     double res = 0;
25     double v = 0;
26     for (int i = 1; i <= n; ++i)
27     {
28         double t = arr[i].s;
29         res += v * t + arr[i].a * t * t / 2;
30         v += arr[i].a * t;
31     }
32     return res;
33 }
34 
35 int main()
36 {
37     while (scanf("%d", &n) != EOF)
38     {
39         for (int i = 1; i <= n; ++i) arr[i].scan();
40         double sum1 = work();
41         sort(arr + 1, arr + 1 + n);
42         double sum2 = work();
43 //        printf("%lf %lf\n", sum1, sum2);
44         printf("%.1f\n", sum2 - sum1);
45     }
46     return 0;
47 }
View Code

 

H:Cat and Mouse

留坑。

 

I:Tetris

留坑。

 

J:Cunning Friends

題意:有n堆石頭,第i堆有ai個,A先取,每次從一堆中取的數量不等於0,而後B 和 C取 誰不能取了誰就輸了,B 和 C 想讓A輸,假設每一個人的決策都是最佳的,求A是必敗仍是必輸

思路:能夠考慮一下幾種狀況

1° 全是1的狀況  那麼用n%3 看一下餘數,若是餘數是0 那麼A是必輸的

2°只有一個不是1的狀況,那麼A是必勝的,由於假如堆數%3 == 0 那麼 我將不是1的那堆取成1,這樣就至關於變成了堆數%3==1 變成必勝態

3°有兩個不是1的狀況

首先咱們能夠知道,假如只有兩堆,而且這兩堆都不是1,那麼A是必輸的

那轉化成加了若干堆1,那麼這若干堆1當中若是%3 == 0 那麼A是必輸的

若是不是,而且存在至少一堆是2,A是贏的

4° 其餘狀況都是必輸的

 1 #pragma comment(linker, "/STACK:1024000000,1024000000") 
 2 
 3 #include <cstdio>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <iostream>
 7 
 8 using namespace std;
 9 
10 #define INF 0x3f3f3f3f
11 #define INFLL 0x3f3f3f3f3f3f3f3f
12 #define ll long long 
13 #define N 100100
14 
15 int n;
16 
17 int ONE, TWO;
18 
19 inline bool work()
20 {
21     if (ONE == n - 1) return true;
22     else if (ONE == n)
23         return n % 3;
24     if (ONE == n - 2)
25     {
26         if (n % 3 == 2) return false;
27         if (TWO) return true;
28         return false;
29     }
30     return false;
31 }
32 
33 inline void Run()
34 {
35     while (scanf("%d", &n) != EOF)
36     {
37         ONE = 0, TWO = 0;
38         for (int i = 1, num; i <= n; ++i)
39         {
40             scanf("%d", &num);
41             if (num == 1) ++ONE;
42             if (num == 2) ++TWO;
43         }
44         puts(work() ? "Win" : "Lose");
45     }
46 }
47 
48 int main()
49 {
50     #ifdef LOCAL
51         freopen("Test.in", "r", stdin);
52     #endif
53 
54     Run();
55     
56     return 0;
57 }
View Code

 

 

 

k:Escape Room

題意:有一個長度爲n的序列,裏面的數是1 - n 而後給出每一位以當前位爲隊頭的最長上升子序列長度,還原原序列,多個答案輸出字典序最小的那個

思路:

好比說 1 2 2 1

咱們能夠考慮先放長度爲1 的

確定是從後面取兩個數 放 4 和 3

而後 長度就變成

0 1 1 0

而後又取兩個 2 1 放下去

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define N 10010
 6 
 7 struct node
 8 {
 9     double a, s;
10     inline void scan()
11     {
12         scanf("%lf%lf", &a, &s);
13     }
14     inline bool operator < (const node &r) const
15     {
16         return a  > r.a;
17     }
18 }arr[N];
19 
20 int n;
21 
22 inline double work()
23 {
24     double res = 0;
25     double v = 0;
26     for (int i = 1; i <= n; ++i)
27     {
28         double t = arr[i].s;
29         res += v * t + arr[i].a * t * t / 2;
30         v += arr[i].a * t;
31     }
32     return res;
33 }
34 
35 int main()
36 {
37     while (scanf("%d", &n) != EOF)
38     {
39         for (int i = 1; i <= n; ++i) arr[i].scan();
40         double sum1 = work();
41         sort(arr + 1, arr + 1 + n);
42         double sum2 = work();
43 //        printf("%lf %lf\n", sum1, sum2);
44         printf("%.1f\n", sum2 - sum1);
45     }
46     return 0;
47 }
View Code

 

L:Divide and Conquer

留坑。

相關文章
相關標籤/搜索