CCPC-Wannafly Winter Camp Day2 (Div2, onsite)

Class


$A_i = a \cdot i \% n$

有 $A_i = k \cdot gcd(a, n)$

证明:

$A_0 = 0, A_x = x \cdot a - y \cdot n$

$令 d = gcd(a, n)$

$A_x \% d = (x \cdot a \% d - y \cdot n \% d) \% d = 0$ 得证

循环节为$\frac {n}{gcd(a, n)}$

Replay


Dup4:

  • 自闭了,啥都不会,想开一道无人做的字符串,喵喵喵?
  • 总是陷入思维的泥浆,爬不出来,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

猜你喜欢

转载自www.cnblogs.com/Dup4/p/10301355.html