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 }
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 }
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 }
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 }
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 }
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 }
L:Divide and Conquer
留坑。