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 }
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 }
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 }
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 * dx) mod n, (2 * dy) mod n) - ... - (((n - 1) * dx) mod n, ((n - 1) * dy) mod 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) * dx) mod n] = ((n - 1) * dy) mod 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] + k) mod n = yi, k = (yi - y[xi] + n) mod 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 }

浙公网安备 33010602011771号