CF #280 div2

2014-12-02 12:07:27

总结:比赛一小时左右A到了d题(本手速党丧病水到了第一版orz...)后来一小时瞎搞YY e题失败- -!赛后d被fst,呼呼,后来发现是二分范围少打几个零的我眼泪掉下来~。

  e题是个数学题,智商不够 hhhh- -、

A:模拟(可以推公式加速..)

 1 /*************************************************************************
 2     > File Name: a.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Tue 02 Dec 2014 12:30:57 AM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 
27 int n;
28 
29 int main(){
30     scanf("%d",&n);
31     int i,cnt = 0;
32     for(i = 1; ; ++i){
33         cnt += i;
34         n -= cnt;
35         if(n <= 0){
36             if(n < 0) --i;
37             break;
38         }
39     }
40     printf("%d\n",i);
41     return 0;
42 }
View Code

B:模拟,注意下两端

 1 /*************************************************************************
 2     > File Name: b.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Tue 02 Dec 2014 12:34:58 AM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 
27 int n,l,p[1010];
28 
29 int main(){
30     scanf("%d%d",&n,&l);
31     for(int i = 1; i <= n; ++i){
32         scanf("%d",&p[i]);
33     }
34     sort(p,p + n + 1);
35     double tmax = 0;
36     for(int i = 0; i < n; ++i){
37         tmax = max(tmax,(double)(p[i + 1] - p[i]));
38     }
39     tmax = max(1.0 * tmax / 2,(double)max(p[1],l - p[n]));
40     printf("%.9f\n",tmax);
41     return 0;
42 }
View Code

C:排序模拟,long long,无坑

 1 /*************************************************************************
 2     > File Name: c.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Tue 02 Dec 2014 12:42:26 AM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 
27 ll n,r,avg;
28 ll sum;
29 
30 struct node{
31     ll a,b;
32 }t[100010];
33 
34 bool cmp(node A,node B){
35     return A.b < B.b;
36 }
37 
38 int main(){
39     scanf("%I64d%I64d%I64d",&n,&r,&avg);
40     avg *= n;
41     sum = 0;
42     for(int i = 1; i <= n; ++i){
43         scanf("%I64d%I64d",&t[i].a,&t[i].b);
44         sum += t[i].a;
45     }
46     ll ned = avg - sum;
47     if(ned <= 0){
48         printf("0\n");
49         return 0;
50     }
51     sort(t + 1,t + n + 1,cmp);
52     ll ans = 0;
53     for(int i = 1; i <= n; ++i){
54         ll k = r - t[i].a;
55         if(k >= ned){
56             ans += ned * t[i].b;
57             ned = 0;
58             break;
59         }
60         else{
61             ans += k * t[i].b;
62             ned -= k;
63         }
64     }
65     printf("%I64d\n",ans);
66     return 0;
67 }
View Code

D:- = YY完一敲就A了...果然有点问题

  其实可以把问题转化为两端长列,长列1上每隔y距离有一个点,长列2上每隔x距离有一个点(至于为什么,a / x == b / y --> ay == bx,^_^)

  思考可知,每个点能打小怪兽一下,然后就直接二分检查在哪个位置能杀死monster。

  在过程中再加个优化,在lcm(x,y)处两点重合,所以可以将monster血量整除(lcm / x + lcm / y)的部分省略考虑,最后余下的数肯定 <= 10^12,那么就用这个范围二分,搞定。

 1 /*************************************************************************
 2     > File Name: d.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Tue 02 Dec 2014 12:53:01 AM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 const ll RA = 1e12;
27 
28 ll Gcd(ll aa,ll bb){
29     return bb == 0 ? aa : Gcd(bb,aa % bb);
30 }
31 
32 int n;
33 ll v[100010];
34 ll a,b,Lcm,g;
35 
36 ll B_search(ll val){
37     ll l = 0,r = RA;
38     while(l < r){
39         ll mid = getmid(l,r);
40         if(mid / a + mid / b >= val)
41             r = mid;
42         else
43             l = mid + 1;
44     }
45     return l;
46 }
47 
48 int main(){
49     scanf("%d%I64d%I64d",&n,&a,&b);
50     g = Gcd(a,b);
51     Lcm = a / g * b;
52     ll num = Lcm / a + Lcm / b;
53     for(int i = 1; i <= n; ++i){
54         scanf("%I64d",&v[i]);
55         v[i] = v[i] - v[i] / num * num;
56         ll ans = B_search(v[i]);
57         if(ans % a == 0 && ans % b == 0){
58             printf("Both\n");
59         }
60         else if(ans % b == 0){
61             printf("Vanya\n");
62         }
63         else{
64             printf("Vova\n");
65         }
66     }
67     return 0;
68 }

E:作者的题解写的很好,大意就是:因为dx、n;dy、n都互质,所以从一个点出发走n步才能结束,考虑以第一排的各个点作为起点。首先考虑(0,0),依次到达:(dx,dy),(2*dx%n,2*dy%n),....,(k*dx%n,k*dy%n)(1<=k<=n),再考虑从(0,p)出发,到达:(dx,(dy+p)%n) , (2*dx%n,(2*dy+p)%n),....,(k*dx%n,(k*dy+p)%n)),那么我们发现其实只要算从(0,0)出发的情况,并用映射数组记录 Y[k*dx%n] = k*dy%n。那么从(0,p)出发的情况就是:Y[k*dx%n]+p = k*dy%n。

  对于每颗树,我们要判断它能从哪个起点出发到达,建立方程:Y[xi] + p = yi (mod n) , p = (yi - Y[xi] + n) % n,在过程中记录每个起点被判到的次数,最后取最大值。

附作者题解:

As long as gcd(dx, n) = gcd(dy, n) = 1, Vanya will do full cycle for n moves. Let's group all possible pathes into n groups, where 1 - th, 2 - nd, ... , n - th path will be started from points (0, 0), (0, 1), …, (0, n - 1). Let's look on first path: (0, 0) - (dx, dy) - ((2 * dxmod n, (2 * dymod n) - ... - (((n - 1) * dxmod n, ((n - 1) * dymod n). As long as gcd(dx, n) = 1, among the first coordinates of points of the path there will be all the numbers from 0 to n - 1. So we can write in the array all relations between the first and second coordinate in points for the path, that starts in the point (0, 0), i.e. y[0] = 0, y[dx] = dy, ... , y[((n - 1) * dxmod n] = ((n - 1) * dymod n. Now we know, that all points with type(i, y[i]), where 0 ≤ i ≤ n - 1, belong to the group with start point (0, 0). In that case, points with type (i, (y[i] + k)modn) belong to the group with start point (0, k). Then we can add every point (xi, yi) to required group k for О(1): (y[xi] + kmod n = yi, k = (yi - y[xi] + nmod n. Then we need just to find group with the maximal amount of elements, it will be the answer.

Time complexity O(n).

 1 /*************************************************************************
 2     > File Name: e.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com 
 5     > Created Time: Tue 02 Dec 2014 01:21:45 AM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 
27 int n,m,dx,dy;
28 int X,Y;
29 int y[1000010];
30 int num[1000010];
31 
32 void Pre(){
33     int s1 = 0,s2 = 0;
34     y[0] = 0;
35     for(int i = 1; i <= n; ++i){
36         s1 = (s1 + dx) % n;
37         s2 = (s2 + dy) % n;
38         y[s1] = s2;
39     }
40 }
41 
42 int main(){
43     scanf("%d%d%d%d",&n,&m,&dx,&dy);
44     Pre();
45     for(int i = 1; i <= m; ++i){
46         scanf("%d%d",&X,&Y);
47         num[(Y - y[X] + n) % n]++;
48     }
49     int tmax = 0,ans;
50     for(int i = 0; i <= 1000000; ++i){
51         if(num[i] > tmax){
52             tmax = num[i];
53             ans = i;
54         }
55     }
56     printf("%d %d\n",0,ans);
57     return 0;
58 }

 

posted @ 2014-12-02 21:02  Naturain  阅读(106)  评论(0)    收藏  举报