Classnode
$A_i = a \cdot i \% n$c++
有 $A_i = k \cdot gcd(a, n)$ide
證實:優化
$A_0 = 0, A_x = x \cdot a - y \cdot n$spa
$令 d = gcd(a, n)$code
$A_x \% d = (x \cdot a \% d - y \cdot n \% d) \% d = 0$ 得證blog
循環節爲$\frac {n}{gcd(a, n)}$排序
Replay字符串
Dup4:get
X:
Solution
A: Erase Numbers II
思路:
$n^2 暴力 注意最大的那項會爆 long\; long 但不會爆 unsigned \;long \;long$
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef unsigned long long ull; 6 const int maxn = 1e5 + 10; 7 8 int n; 9 ull arr[maxn]; 10 ull len[maxn]; 11 12 int main() 13 { 14 int t; 15 scanf("%d", &t); 16 for(int cas = 1; cas <= t; ++cas) 17 { 18 printf("Case #%d: ", cas); 19 scanf("%d", &n); 20 for(int i = 1; i <= n; ++i) 21 { 22 scanf("%llu", arr + i); 23 len[i] = 1; 24 ull x = arr[i]; 25 while(x) 26 { 27 len[i] *= 10; 28 x /= 10; 29 } 30 } 31 ull ans = 0; 32 for(int i = 1; i <= n; ++i) 33 { 34 for(int j = i + 1; j <= n; ++j) 35 { 36 ans = max(ans, arr[i] * len[j] + arr[j]); 37 } 38 } 39 printf("%llu\n", ans); 40 } 41 return 0; 42 }
B: Erase Numbers I
思路:
$將刪除兩個數當作兩次操做$
$每次操做刪除剩餘串中長度最小$
$先O(n)掃一遍,若是找到一個長度最小而且字典序小於後一位的,便可直接上出,而且保證了最優$
$若是第一遍掃沒找到合適的, 就從後往前找到第一個長度最小的刪除$
$作兩遍便可$
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int INF = 0x3f3f3f3f; 6 const int maxn = 1e4 + 10; 7 8 struct node{ 9 char str[20]; 10 int len; 11 int flag; 12 }arr[maxn]; 13 14 int n; 15 16 int main() 17 { 18 int t; 19 scanf("%d", &t); 20 for(int cas = 1; cas <= t; ++cas) 21 { 22 printf("Case #%d: ", cas); 23 scanf("%d", &n); 24 for(int i = 1; i <= n; ++i) 25 { 26 scanf("%s", arr[i].str); 27 arr[i].len = strlen(arr[i].str); 28 arr[i].flag = 0; 29 } 30 int pos1 = -1, pos2 = -1; 31 int Min = INF; 32 for(int i = 1; i <= n; ++i) if(!arr[i].flag) Min = min(Min, arr[i].len); 33 for(int i = 1; i <= n; ++i) 34 { 35 if(arr[i].flag) continue; 36 if(Min != arr[i].len) continue; 37 int j = i + 1; 38 while(arr[j].flag && j <= n) ++j; 39 if(j <= n) 40 { 41 if(strcmp(arr[i].str, arr[j].str) < 0) 42 { 43 pos1 = i; 44 arr[i].flag = 1; 45 break; 46 } 47 } 48 } 49 if(pos1 == -1) 50 { 51 for(int i = n; i >= 1; --i) 52 { 53 if(arr[i].flag) continue; 54 if(arr[i].len == Min) 55 { 56 arr[i].flag = 1; 57 pos1 = i; 58 break; 59 } 60 } 61 } 62 Min = INF; 63 for(int i = 1; i <= n; ++i) if(!arr[i].flag) Min = min(Min, arr[i].len); 64 for(int i = 1; i <= n; ++i) 65 { 66 if(arr[i].flag) continue; 67 if(Min != arr[i].len) continue; 68 int j = i + 1; 69 while(arr[j].flag && j <= n) ++j; 70 if(j <= n) 71 { 72 if(strcmp(arr[i].str, arr[j].str) < 0) 73 { 74 pos2 = i; 75 arr[i].flag = 1; 76 break; 77 } 78 } 79 } 80 if(pos2 == -1) 81 { 82 for(int i = n; i >= 1; --i) 83 { 84 if(arr[i].flag) continue; 85 if(arr[i].len == Min) 86 { 87 arr[i].flag = 1; 88 pos2 = i; 89 break; 90 } 91 } 92 } 93 for(int i = 1; i <= n; ++i) if(!arr[i].flag) printf("%s", arr[i].str); 94 puts(""); 95 } 96 return 0; 97 }
H: Cosmic Cleaner
思路:
$球缺體積$
$用一個平面截去一個球所得部分叫球缺$
$球缺面積 = 2 \cdot \pi h$
$球缺體積 = \pi \cdot h^2 \cdot (R - \frac{h}{3})$
$球缺質心:勻質球缺的質心位於它的中軸線上,而且與底面的距離爲$
$C = \frac{(4\cdot R - h) \cdot h}{12 \cdot R - 4 \cdot h} = \frac{(d^2 + 2\cdot h^2) \cdot h}{3\cdot d^2 + 4\cdot h^2}$
$而後分分類 搞一搞,就行了$
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const double eps = 1e-8; 6 const double PI = acos(-1.0); 7 const int maxn = 1e2 + 10; 8 9 int sgn(double x) 10 { 11 if(fabs(x) < eps) return 0; 12 else return x > 0 ? 1 : -1; 13 } 14 15 struct node{ 16 double x, y, z, r; 17 node(){} 18 node(double x, double y, double z, double r): x(x), y(y), z(z), r(r){} 19 }O, P[maxn]; 20 21 double getdis(node p1, node p2) 22 { 23 double res = (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z); 24 res = sqrt(res); 25 return res; 26 } 27 28 int n; 29 30 int main() 31 { 32 int t; 33 scanf("%d", &t); 34 for(int cas = 1; cas <= t; ++cas) 35 { 36 printf("Case #%d: ", cas); 37 scanf("%d", &n); 38 for(int i = 1; i <= n; ++i) 39 { 40 scanf("%lf %lf %lf %lf", &P[i].x, &P[i].y, &P[i].z, &P[i].r); 41 } 42 scanf("%lf %lf %lf %lf", &O.x, &O.y, &O.z, &O.r); 43 double ans = 0; 44 for(int i = 1; i <= n; ++i) 45 { 46 double dis = getdis(O, P[i]); 47 double tmp = dis - O.r - P[i].r; 48 //out 49 if(sgn(tmp) > 0) 50 { 51 continue; 52 } 53 54 //in 55 if(sgn(dis + P[i].r - O.r) <= 0) 56 { 57 double tmp1 = 4.0 / 3.0 * PI * P[i].r * P[i].r * P[i].r; 58 ans += tmp1; 59 continue; 60 } 61 62 //part1 63 double r1 = O.r, r2 = P[i].r; 64 65 double r0 = (r1 * r1 + dis * dis - r2 * r2) / (2.0 * dis); 66 double h1 = r1 - r0; 67 68 ans += PI * h1 * h1 * (r1 - h1 / 3.0); 69 70 //part2 71 r0 = (r2 * r2 + dis * dis - r1 * r1) / (2.0 * dis); 72 double h2 = r2 - r0; 73 ans += PI * h2 * h2 * (r2 - h2 / 3.0); 74 } 75 printf("%.10f\n", ans); 76 } 77 return 0; 78 }
K: Sticks
思路:
將$l_i排序,接着n^3處理出合法的三角形關係,而後枚舉三角形關係$
$注意不要重複枚舉,可是暴力枚舉常數仍是太大$
$考慮一條剪枝,若是有一個三角關係,令其爲a_1, a_2, a_3$
$若是存在 a_x >= a_3 和 a_1 以及 a_2 也一樣知足大小關係,那麼這個三角關係不用枚舉$
$由於咱們是從小到大枚舉,在二三層循環當中枚舉到的點的長度確定比第一層的要大$
$那麼對於a_x >= a_3 將a_x留在後面的三角關係中會使得答案更優$
而後就過了..
但實際上有一種更爲科學的?方法
考慮合法的不重複的四對三角關係只有$\frac {C_{12}^3 \cdot C_{9}^3 \cdot C_6^3 }{4!}$
只有$15400 若是可以預處理出來,再暴力枚舉的時間複雜度是對的$
考慮如何預處理
顯然有個$O(220^4)的方法$
那麼咱們考慮可否優化掉第四維的$220$
$其實前三個三角關係肯定了,第四個天然肯定了,可是咱們須要去重啊$
先考慮不重不漏的枚舉三角關係 從小到大,而且每個三角關係都有惟一編號
$用 Hash[][][] 進行Hash$
這樣就能夠$O(1)獲得剩下的那個三角關係的編號,考慮編號和前三個三角關係編號的大小$
若是小了,那麼確定重複了
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 15 5 int t, l[N], vis[N]; 6 struct node 7 { 8 int x, y, z; 9 node () {} 10 node (int x, int y, int z) : x(x), y(y), z(z) {} 11 }; vector <node> v; 12 vector <int> res; 13 int Stack[100010], top; 14 15 bool ok(int x, int y, int z) 16 { 17 if (x + y > z && x + z > y && y + z > x) return 1; 18 return 0; 19 } 20 21 bool used(node a) 22 { 23 if (!vis[a.x] && !vis[a.y] && !vis[a.z]) return 0; 24 return 1; 25 } 26 27 void work(int i) 28 { 29 Stack[++top] = v[i].x; 30 Stack[++top] = v[i].y; 31 Stack[++top] = v[i].z; 32 vis[v[i].x] = 1; 33 vis[v[i].y] = 1; 34 vis[v[i].z] = 1; 35 } 36 37 void clear(int i) 38 { 39 top -= 3; 40 vis[v[i].x] = 0; 41 vis[v[i].y] = 0; 42 vis[v[i].z] = 0; 43 } 44 45 void add() 46 { 47 if (top > res.size()) 48 { 49 res.clear(); 50 for (int o = 1; o <= top; ++o) res.push_back(Stack[o]); 51 } 52 } 53 54 void solve() 55 { 56 int m = v.size(); 57 for (int i = 0; i < m; ++i) if (i == 0 || !(v[i].x == v[i - 1].x && v[i].y == v[i - 1].y)) 58 { 59 work(i); add(); 60 for (int j = i + 1; j < m; ++j) if (!used(v[j])) 61 { 62 work(j); add(); 63 for (int k = j + 1; k < m; ++k) if (!used(v[k])) 64 { 65 work(k); add(); 66 int a[3] = {0}, cnt = 0; 67 for (int o = 1; o <= 12; ++o) if (!vis[o]) 68 a[cnt++] = o; 69 if (ok(l[a[0]], l[a[1]], l[a[2]])) 70 { 71 for (int o = 0; o < 3; ++o) Stack[++top] = a[o]; 72 add(); 73 return; 74 } 75 clear(k); 76 } 77 clear(j); 78 } 79 clear(i); 80 } 81 } 82 83 int main() 84 { 85 scanf("%d", &t); 86 for (int kase = 1; kase <= t; ++kase) 87 { 88 printf("Case #%d: ", kase); top = 0; res.clear(); 89 memset(vis, 0, sizeof vis); 90 for (int i = 1; i <= 12; ++i) scanf("%d", l + i); 91 sort(l + 1, l + 13); 92 v.clear(); 93 for (int i = 1; i <= 12; ++i) for (int j = i + 1; j <= 12; ++j) for (int k = j + 1; k <= 12; ++k) if (ok(l[i], l[j], l[k])) 94 v.push_back(node(i, j, k)); 95 solve(); 96 int k = res.size() / 3; 97 printf("%d\n", k); 98 for (int i = 0, len = res.size(); i < len; ++i) printf("%d%c", l[res[i]], " \n"[(i + 1) % 3 == 0]); 99 } 100 return 0; 101 }
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 15 5 #define M 200100 6 int t, n, l[N], vis[N]; 7 8 struct node 9 { 10 int a[3]; 11 node () {} 12 node (int x, int y, int z) 13 { 14 a[0] = x; 15 a[1] = y; 16 a[2] = z; 17 } 18 bool ok() 19 { 20 if (l[a[0]] + l[a[1]] > l[a[2]] && l[a[0]] + l[a[2]] > l[a[1]] && l[a[1]] + l[a[2]] > l[a[0]]) return 1; 21 return 0; 22 } 23 void out() 24 { 25 for (int i = 0; i < 3; ++i) printf("%d%c", l[a[i]], " \n"[i == 2]); 26 } 27 }; vector <node> vec; 28 node que[M][5]; 29 node Stack[110]; int top; 30 int Hash[15][15][15]; 31 32 void used(node x) { for (int i = 0; i < 3; ++i) vis[x.a[i]] = 1; } 33 void clear(node x) { for (int i = 0; i < 3; ++i) vis[x.a[i]] = 0; --top; } 34 bool notused(node x) { for (int i = 0; i < 3; ++i) if (vis[x.a[i]]) return false; return true; } 35 36 void init() 37 { 38 int m = 0; 39 for (int i = 1; i <= 12; ++i) for (int j = i + 1; j <= 12; ++j) for (int k = j + 1; k <= 12; ++k) 40 { 41 vec.push_back(node(i, j, k)); 42 Hash[i][j][k] = m; 43 ++m; 44 } 45 n = 0; top = 0; 46 for (int i = 0; i < m; ++i) 47 { 48 Stack[++top] = vec[i]; 49 used(vec[i]); 50 for (int j = i + 1; j < m; ++j) if (notused(vec[j])) 51 { 52 Stack[++top] = vec[j]; 53 used(vec[j]); 54 for (int k = j + 1; k < m; ++k) if (notused(vec[k])) 55 { 56 Stack[++top] = vec[k]; 57 used(vec[k]); 58 node tmp; int cnt = 0; 59 for (int o = 1; o <= 12; ++o) if (!vis[o]) 60 tmp.a[cnt++] = o; 61 if (Hash[tmp.a[0]][tmp.a[1]][tmp.a[2]] > k) 62 { 63 Stack[++top] = tmp; 64 ++n; 65 for (int o = 1; o <= top; ++o) que[n][o] = Stack[o]; 66 --top; 67 } 68 clear(vec[k]); 69 } 70 clear(vec[j]); 71 } 72 clear(vec[i]); 73 } 74 } 75 76 int main() 77 { 78 init(); 79 scanf("%d", &t); 80 for (int kase = 1; kase <= t; ++kase) 81 { 82 printf("Case #%d: ", kase); 83 for (int i = 1; i <= 12; ++i) scanf("%d", l + i); 84 vector <node> res, tmp; 85 for (int i = 1; i <= n; ++i) 86 { 87 tmp.clear(); 88 for (int j = 1; j <= 4; ++j) if (que[i][j].ok()) 89 tmp.push_back(que[i][j]); 90 if (tmp.size() > res.size()) res = tmp; 91 if (res.size() == 4) break; 92 } 93 int k = res.size(); 94 printf("%d\n", k); 95 for (int i = 0; i < k; ++i) res[i].out(); 96 } 97 return 0; 98 }