CCPC-Wannafly Winter Camp Day2 (Div2, onsite)

 

 

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

  • 自閉了,啥都不會,想開一道無人作的字符串,喵喵喵?
  • 老是陷入思惟的泥漿,爬不出來,T那麼大,怎麼就想不到預處理呢

 X:

  • 成功晉升碼農
  • 第三次忘記預處理是個啥,最後全靠隊友一波rush
  • 平常開局血崩,這口鍋必需要背

 

 

 

 

 

 

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 }
View Code

 

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 }
View Code

 

 

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}$

$其中,h爲球缺的高,R爲大圓半徑,d爲球缺的底面直徑$

$而後分分類 搞一搞,就行了$

 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 }
View Code

 

 

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 }
View Code
 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 }
View Code
相關文章
相關標籤/搜索