ACdream原创群赛(15)の每题10s多开心 非官方题解

2014年7月4日,ACdream群赛简单题解。 5道是本弱出的,5道是适牛出的。 写个简单的题解。 具体题解见适牛的详细版!

A:

喵喵的数字

我的做法就是数位DP 数位DP可以求, <=n 里面,二进制1的个数有num个的有多少个,以及他们的和。 然后num从小到大去变化。 然后二分就可以找出第M个数是什么,和也知道了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/* ***************

Author :kuangbin

Created Time :2014/6/30 21:44:09

File Name :E:\2014ACM\题目\数字.cpp

************************************************ */

#include <stdio.h>

#include <string.h>

#include <iostream>

#include <algorithm>

#include <vector>

#include <queue>

#include <set>

#include <map>

#include <string>

#include <math.h>

#include <stdlib.h>

#include <time.h>

using namespace std;

const int MOD = 1e9+9;

long long dp1[100][100],dp2[100][100];

int bit[100];

long long two[100];

pair<long long,long long> dfs(int pos,int num,bool flag)

{

if(pos == -1)

{

if(num == 0)return make_pair(1,0);

else return make_pair(0,0);

}

if(num < 0)return make_pair(0,0);

if(!flag && dp1[pos][num] != -1)return make_pair(dp1[pos][num],dp2[pos][num]);

long long ans1 = 0, ans2 = 0;

int end = flag?bit[pos]:1;

pair<long long,long long>tmp;

for(int i = 0;i <= end;i++)

{

tmp = dfs(pos-1,i==1?num-1:num,flag&&i==end);

ans1 += tmp.first;

ans2 += (i*tmp.first%MOD*(two[pos]%MOD)%MOD + tmp.second)%MOD;

if(ans2 >= MOD)ans2 -= MOD;

}

if(!flag)

{

dp1[pos][num] = ans1;

dp2[pos][num] = ans2;

}

return make_pair(ans1,ans2);

}

pair<long long,long long> solve(long long n,int num)

{

int cnt = 0;

do

{

bit[cnt++] = n&1;

n >>= 1;

}

while(n);

return dfs(cnt-1,num,1);

}

pair<long long,long long>p;

int main()

{

//freopen("in.txt","r",stdin);

//freopen("out.txt","w",stdout);

memset(dp1,-1,sizeof(dp1));

memset(dp2,-1,sizeof(dp2));

two[0] = 1;

for(int i = 1;i < 63;i++)

two[i] = 2*two[i-1];

long long n,m;

int T;

scanf("%d",&T);

while(T--)

{

scanf("%lld%lld",&n,&m);

long long ans1;

long long ans2 = 0;

m++;

long long cnt = 0;

for(int i = 0;i <= 63;i++)

{

p = solve(n,i);

if(cnt + p.first < m)

{

cnt += p.first;

ans2 = (ans2 + p.second)%MOD;

continue;

}

long long l = 0, r = n;

while(l <= r)

{

long long mid = (l+r)/2;

p = solve(mid,i);

if(cnt + p.first >= m)

{

ans1 = mid;

r = mid-1;

}

else

l = mid+1;

}

p = solve(ans1,i);

ans2 = (ans2 + p.second)%MOD;

break;

}

printf("%lld %lld\n",ans1,ans2);

}

return 0;

}

B:

Rankings

DP。 填坑法DP。 用dp[i][j] 表示 前i个里面,出来j个, 但是坑的数量不是j的,需要差值去算。 有明确位置的点,要去除,被占的也去除。 DP直接转移就可以了。 dp[n][0]就是答案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
/* ***************

Author :kuangbin

Created Time :2014/6/18 17:05:27

File Name :E:\2014ACM\题目\Rankings\std.cpp

************************************************ */

#include <stdio.h>

#include <string.h>

#include <iostream>

#include <algorithm>

#include <vector>

#include <queue>

#include <set>

#include <map>

#include <string>

#include <math.h>

#include <stdlib.h>

#include <time.h>

#include <assert.h>

using namespace std;

const int MAXN = 1010;

const int MOD = 2014;

const int INF = 0x3f3f3f3f;

struct Node

{

int index;

int dx;

}node[MAXN];

bool cmp(Node a,Node b)

{

return a.index < b.index;

}

int getnext()

{

char ch;

ch = getchar();

while(ch != '-' && ch != '+' && (ch < '0' || ch >'9'))

ch = getchar();

if(ch == '-')

{

ch = getchar();

if(ch < '0' || ch > '9')

return -INF;

int ret = ch - '0';

while(ch = getchar(), ch >= '0' && ch <= '9')

ret = ret*10 + (ch - '0');

return -ret;

}

else if(ch == '+')

{

ch = getchar();

if(ch < '0' || ch > '9')

return INF;

int ret = ch - '0';

while(ch = getchar(), ch >= '0' && ch <= '9')

ret = ret*10 + (ch - '0');

return ret;

}

else

{

int ret = ch - '0';

while(ch = getchar(), ch >= '0' && ch <= '9')

ret = ret*10 + (ch - '0');

return ret;

}

}

int loc[MAXN];

void Add(int &a,int b)

{

a += b;

if(a >= MOD)a -= MOD;

}

int dp[MAXN][MAXN];

bool f[MAXN][MAXN];

int num1[MAXN],num2[MAXN];//坑和可以提供的

int main()

{

//freopen("5.in","r",stdin);

//freopen("5.out","w",stdout);

int iCase = 0;

int n;

while(scanf("%d",&n) == 1)

{

iCase++;

for(int i = 0;i < n;i++)scanf("%d",&node[i].index);

for(int i = 0;i < n;i++)node[i].dx = getnext();

sort(node,node+n,cmp);

memset(loc,0,sizeof(loc));

bool flag = true;

for(int i = 0;i < n;i++)

{

if(node[i].dx == INF || node[i].dx == -INF)continue;

int nn = node[i].index + node[i].dx;

if(nn <= 0 || nn > n)

{

flag = false;

break;

}

loc[nn]++;

if(loc[nn] > 1)

{

flag = false;

break;

}

}

if(!flag)

{

printf("IMPOSSIBLE\n");

continue;

}

num1[0] = num2[0] = 0;

for(int i = 1;i <= n;i++)

{

num1[i] = num1[i-1];

if(loc[i] == 0)num1[i]++;

num2[i] = num2[i-1];

if(node[i-1].dx == INF || node[i-1].dx == -INF)

num2[i]++;

}

memset(dp,0,sizeof(dp));

dp[0][0] = 1;

memset(f,false,sizeof(f));

f[0][0] = true;

for(int i = 0;i < n;i++)

for(int j = 0;j <= n;j++)

{

if(!f[i][j])continue;

if(node[i].dx == 0)

{

Add(dp[i+1][j],dp[i][j]);

f[i+1][j] = true;

continue;

}

int kj = j + (num1[i]-num2[i]);//坑的数量

assert(kj>=0);

//cout<<kj<<endl;

if(node[i].dx != INF && node[i].dx != -INF)

{

if(loc[i+1])

{

Add(dp[i+1][j],dp[i][j]);

f[i+1][j] = true;

}

else

{

Add(dp[i+1][j],dp[i][j]);

f[i+1][j] = true;

if(j)

{

Add(dp[i+1][j-1],(long long)dp[i][j]*j%MOD);

f[i+1][j-1] = true;

}

}

continue;

}

if(node[i].dx == INF)

{

if(loc[i+1])

{

Add(dp[i+1][j+1],dp[i][j]);

f[i+1][j+1] = true;

}

else

{

Add(dp[i+1][j+1],dp[i][j]);

f[i+1][j+1] = true;

if(j)

{

Add(dp[i+1][j],(long long)dp[i][j]*j%MOD);

f[i+1][j] = true;

}

}

}

else

{

if(loc[i+1])

{

if(kj)

{

Add(dp[i+1][j],(long long)dp[i][j]*kj%MOD);

f[i+1][j] = true;

}

}

else

{

if(kj)

{

Add(dp[i+1][j],(long long)dp[i][j]*kj%MOD);

f[i+1][j] = true;

if(j)

{

Add(dp[i+1][j-1],(long long)dp[i][j]*kj*j%MOD);

f[i+1][j-1] = true;

}

}

}

}

}

if(!f[n][0])printf("IMPOSSIBLE\n");

else

printf("%d\n",dp[n][0]);

}

return 0;

}

C:

喵喵去寻宝

董壕的神几何。 我是用求积分的方法算的,精度误差比较大,我要1e-3的误差才能过。 我就是吧五角星变成10条有向线段。 线段和抛物线求面积。 求交点,然后解析法求积分。 图就不画了,画起来麻烦。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
/* ***************

Author :kuangbin

Created Time :2014/7/1 22:36:20

File Name :E:\2014ACM\题目\xunbao.cpp

************************************************ */

#include <stdio.h>

#include <string.h>

#include <iostream>

#include <algorithm>

#include <vector>

#include <queue>

#include <set>

#include <map>

#include <string>

#include <math.h>

#include <stdlib.h>

#include <time.h>

using namespace std;

// 计算几何模板

const double eps = 1e-10;

const double inf = 1e20;

const double pi = acos(-1.0);

const double PI = pi;

const int maxp = 1010;

//Compares a double to zero

int sgn(double x)

{

if(fabs(x) < eps)return 0;

if(x < 0)return -1;

else return 1;

}

//square of a double

inline double sqr(double x){return x*x;}

/*

* Point

* Point() - Empty constructor

* Point(double _x,double _y) - constructor

* input() - double input

* output() - %.2f output

* operator == - compares x and y

* operator < - compares first by x, then by y

* operator - - return new Point after subtracting curresponging x and y

* operator ^ - cross product of 2d points

* operator * - dot product

* len() - gives length from origin

* len2() - gives square of length from origin

* distance(Point p) - gives distance from p

* operator + Point b - returns new Point after adding curresponging x and y

* operator * double k - returns new Point after multiplieing x and y by k

* operator / double k - returns new Point after divideing x and y by k

* rad(Point a,Point b)- returns the angle of Point a and Point b from this Point

* trunc(double r) - return Point that if truncated the distance from center to r

* rotleft() - returns 90 degree ccw rotated point

* rotright() - returns 90 degree cw rotated point

* rotate(Point p,double angle) - returns Point after rotateing the Point centering at p by angle radian ccw

*/

struct Point

{

double x,y;

Point(){}

Point(double _x,double _y)

{

x = _x;

y = _y;

}

void input()

{

scanf("%lf%lf",&x,&y);

}

void output()

{

printf("%.2f %.2f\n",x,y);

}

bool operator == (Point b)const

{

return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;

}

bool operator < (Point b)const

{

return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x;

}

Point operator -(const Point &b)const

{

return Point(x-b.x,y-b.y);

}

//叉积

double operator ^(const Point &b)const

{

return x*b.y - y*b.x;

}

//点积

double operator *(const Point &b)const

{

return x*b.x + y*b.y;

}

//绕着p点逆时针旋转angle

Point rotate(Point p,double angle)

{

Point v = (*this) - p;

double c = cos(angle), s = sin(angle);

return Point(p.x + v.x*c - v.y*s,p.y + v.x*s + v.y*c);

}

};

/*

* Stores two points

* Line() - Empty constructor

* Line(Point _s,Point _e) - Line through _s and _e

* operator == - checks if two points are same

* Line(Point p,double angle) - one end p , another end at angle degree

* Line(double a,double b,double c) - Line of equation ax + by + c = 0

* input() - inputs s and e

* adjust() - orders in such a way that s < e

* length() - distance of se

* angle() - return 0 <= angle < pi

* relation(Point p) - 3 if point is on line

* 1 if point on the left of line

* 2 if point on the right of line

* pointonseg(double p) - return true if point on segment

* parallel(Line v) - return true if they are parallel

* segcrossseg(Line v) - returns 0 if does not intersect

* returns 1 if non-standard intersection

* returns 2 if intersects

* linecrossseg(Line v) - line and seg

* linecrossline(Line v) - 0 if parallel

* 1 if coincides

* 2 if intersects

* crosspoint(Line v) - returns intersection point

* dispointtoline(Point p) - distance from point p to the line

* dispointtoseg(Point p) - distance from p to the segment

* dissegtoseg(Line v) - distance of two segment

* lineprog(Point p) - returns projected point p on se line

* symmetrypoint(Point p) - returns reflection point of p over se

*

*/

struct Line

{

Point s,e;

Line(){}

Line(Point _s,Point _e)

{

s = _s;

e = _e;

}

//求两直线的交点

//要保证两直线不平行或重合

Point crosspoint(Line v)

{

double a1 = (v.e-v.s)^(s-v.s);

double a2 = (v.e-v.s)^(e-v.s);

return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));

}

};

double a1,b1,c1;

double kk,bb;

double f1(double x)

{

return a1*x*x*x/3 + b1*x*x/2 + c1*x;

}

double f2(double x)

{

return kk*x*x/2 + bb*x;

}

double asr(double a,double b)

{

//printf("%lf %lf\n",a,b);

//return asr(a,b,eps,simpson(a,b));

//if(fabs(b-a) < eps)return 0.0;

double mid = (b+a)/2;

double tmp1 = a1*mid*mid + b1*mid + c1;

double tmp2 = kk*mid + bb;

double ans = 0;

if(tmp1 > tmp2)

{

ans = f1(b) - f1(a);

}

else ans = f2(b) - f2(a);

//printf("%.10lf\n",ans);

return ans;

}

double solve(Point s,Point e)

{

double x1 = s.x, y1 = s.y;

double x2 = e.x, y2 = e.y;

if(fabs(x1-x2) < eps)return 0.0;

kk = (y2-y1)/(x2-x1);

bb = y1 - kk*x1;

vector<double>vec;

if(fabs(a1) < eps)

{

if(fabs(b1-bb) < eps)

return asr(x1,x2);

else

{

vec.push_back(x1);

vec.push_back(x2);

double xx = (bb-c1)/(b1-kk);

if( (xx-x1)*(xx-x2) < 0 )

vec.push_back(xx);

sort(vec.begin(),vec.end());

double ans = 0;

int sz = vec.size();

for(int i = 0;i < sz-1;i++)

ans += asr(vec[i],vec[i+1]);

if(x1 > x2)ans = -ans;

return ans;

}

}

double deta = (b1-kk)*(b1-kk) - 4*a1*(c1-bb);

if(fabs(deta) < eps)deta = 0;

if(deta <= -eps)

return asr(x1,x2);

else

{

vec.push_back(x1);

vec.push_back(x2);

double xx = (-(b1-kk)+sqrt(deta))/(2*a1);

if( (xx-x1)*(xx-x2) < 0 )

vec.push_back(xx);

xx = (-(b1-kk)-sqrt(deta))/(2*a1);

if( (xx-x1)*(xx-x2) < 0 )

vec.push_back(xx);

sort(vec.begin(),vec.end());

int sz = vec.size();

double ans = 0;

for(int i = 0;i < sz-1;i++)

ans += asr(vec[i],vec[i+1]);

if(x1 > x2)ans = -ans;

return ans;

}

}

vector<Point>p;

int main()

{

//freopen("0.in","r",stdin);

//freopen("00.out","w",stdout);

int T;

scanf("%d",&T);

while(T--)

{

scanf("%lf%lf%lf",&a1,&b1,&c1);

Point A,B,C,D,E;

A.input();

B.input();

A.y -= 1e7;

B.y -= 1e7;

c1 -= 1e7;

C = A.rotate(B,36.0/180.0*PI);

D = B.rotate(C,36.0/180.0*PI);

E = C.rotate(D,36.0/180.0*PI);

p.clear();

p.push_back(A);

p.push_back(Line(A,E).crosspoint(Line(C,D)));

p.push_back(C);

p.push_back(Line(A,E).crosspoint(Line(B,C)));

p.push_back(E);

p.push_back(Line(D,E).crosspoint(Line(B,C)));

p.push_back(B);

p.push_back(Line(D,E).crosspoint(Line(A,B)));

p.push_back(D);

p.push_back(Line(C,D).crosspoint(Line(A,B)));

double tmp = 0;

int sz = p.size();

/*

for(int i = 0;i < sz;i++)

{

printf("** %lf %lf\n",p[i].x,p[i].y);

}

*/

for(int i = 0;i < sz;i++)

{

double tt1 = solve(p[i],p[(i+1)%sz]);

//cout<<tt1<<endl;

tmp += tt1;

}

if(tmp < 0)tmp = -tmp;

if(fabs(tmp) < eps)tmp = 0.0;

printf("%.8lf\n",tmp);

//cout<<tmp<<endl;

/*

double L = A.distance(B);

double h = L/2 * tan(18.0/180.0*PI);

L = B.distance(Line(E,D).crosspoint(Line(A,B)));

double ans = 5*L*h - tmp;

printf("%.6lf\n",ans);

*/

}

return 0;

}

D:

Maze

最后保留的箱子数肯定是 lcm(n,m)的倍数。 枚举最后的箱子数。 然后使用最小费用最大流去求最小费用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
#include <stdio.h>

#include <string.h>

#include <iostream>

#include <algorithm>

#include <vector>

#include <queue>

#include <set>

#include <map>

#include <string>

#include <math.h>

#include <stdlib.h>

#include <time.h>

using namespace std;

const int MAXN = 2010;

const int MAXM = 400000;

const int INF = 0x3f3f3f3f;

long long gcd(long long a,long long b)

{

if(b == 0)return a;

return gcd(b,a%b);

}

long long lcm(long long a,long long b)

{

return a/gcd(a,b)*b;

}

struct Edge

{

int to,next,cap,flow,cost;

}edge[MAXM];

int head[MAXN],tol;

int pre[MAXN],dis[MAXN];

bool vis[MAXN];

int N;

void init(int n)

{

N = n;

tol = 0;

memset(head,-1,sizeof(head));

}

void addedge(int u,int v,int cap,int cost)

{

edge[tol].to = v;

edge[tol].cap = cap;

edge[tol].cost = cost;

edge[tol].flow = 0;

edge[tol].next = head[u];

head[u] = tol++;

edge[tol].to = u;

edge[tol].cap = 0;

edge[tol].cost = -cost;

edge[tol].flow = 0;

edge[tol].next = head[v];

head[v] = tol++;

}

bool spfa(int s,int t)

{

queue<int>q;

for(int i = 0;i < N;i++)

{

dis[i] = INF;

vis[i] = false;

pre[i] = -1;

}

dis[s] = 0;

vis[s] = true;

q.push(s);

while(!q.empty())

{

int u = q.front();

q.pop();

vis[u] = false;

for(int i = head[u];i != -1;i = edge[i].next)

{

int v = edge[i].to;

if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost)

{

dis[v] = dis[u] + edge[i].cost;

pre[v] = i;

if(!vis[v])

{

vis[v] = true;

q.push(v);

}

}

}

}

if(pre[t] == -1)return false;

else return true;

}

int minCostMaxflow(int s,int t,int &cost)

{

int flow = 0;

cost = 0;

while(spfa(s,t))

{

int Min = INF;

for(int i = pre[t];i != -1;i = pre[edge[i^1].to])

{

if(Min > edge[i].cap - edge[i].flow)

Min = edge[i].cap - edge[i].flow;

}

for(int i = pre[t];i != -1;i = pre[edge[i^1].to])

{

edge[i].flow += Min;

edge[i^1].flow -= Min;

cost += edge[i].cost*Min;

}

flow += Min;

}

return flow;

}

int p[MAXN][MAXN];

int main()

{

//freopen("2.in","r",stdin);

//freopen("2.out","w",stdout);

int n,m;

while(scanf("%d%d",&n,&m) == 2)

{

int x,y;

scanf("%d%d",&x,&y);

for(int i = 0;i < n;i++)

for(int j = 0;j < m;j++)

scanf("%d",&p[i][j]);

int L = lcm(n,m);

int sum = 0;

for(int i = 0;i < n;i++)

for(int j = 0;j < m;j++)

sum += p[i][j];

int ans = sum*y;

for(int s = L;s <= sum;s+=L)

{

init(n+m+2);

for(int i = 0;i < n;i++)

{

addedge(n+m,i,s/n,0);

if(i < n-1)addedge(i,i+1,INF,x);

if(i > 0)addedge(i,i-1,INF,x);

}

for(int i = 0;i < m;i++)

{

addedge(i+n,n+m+1,s/m,0);

if(i < m-1)addedge(i+n,i+n+1,INF,x);

if(i > 0)addedge(i+n,i+n-1,INF,x);

}

for(int i = 0;i < n;i++)

for(int j = 0;j < m;j++)

addedge(i,j+n,p[i][j],0);

int cost;

minCostMaxflow(n+m,n+m+1,cost);

ans = min(ans,y*(sum-s) + cost);

//printf("%d %d\n ",s,ans);

}

printf("%d\n",ans);

}

return 0;

}

E:

喵喵的遗憾

就是求斐波那契数列数列取模的循环节。 经典问题。 对于斐波那契数列数列,求其模n的循环节 对于一个正整数n,我们求Fib数模n的循环节的长度的方法如下: (1)把 \(n\)素因子分解,即 \(n = p_{1}^{a_1}p_{2}^{a_2}…….p_{k}^{a_k}\) (2)分别计算Fib数模每个\(p_{i}^{a_i}\)的循环节长度,假设长度分别是\(x_{1},x_{2},……x_{k}\) (3)那么Fib模n的循环节长度\( lcm(x_{1},x_{2},….x_{k}) \) 从上面三个步骤看来,关键就是求Fib数模每个\(p^{m}\)的循环节长度 这里有一个优美的定理:Fib数模的最小循环节长度等于\( G(p)*p^{m-1} \),其中\(G(p)\)表示Fib数模素数的最小循环节长度。可以看出我们现在最重要的就是求\(G(p)\) 对于求我们利用如下定理: 如果5是模的二次剩余,那么循环节的的长度\(p-1\)是的因子,否则,循环节的长度\(2(p+1)\)是的因子。 顺便说一句,对于小于等于5的素数,我们直接特殊判断,loop(2)=3,loop(3)=8,loop(5)=20。 那么我们可以先求出所有的因子,然后用矩阵快速幂来一个一个判断,这样时间复杂度不会很大。 二次剩余 这样这个问题就解决了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
/* ***************

Author :kuangbin

Created Time :2014/6/27 22:43:58

File Name :E:\2014ACM\题目\Test\A.cpp

************************************************ */

#include <stdio.h>

#include <string.h>

#include <iostream>

#include <algorithm>

#include <vector>

#include <queue>

#include <set>

#include <map>

#include <string>

#include <math.h>

#include <stdlib.h>

#include <time.h>

using namespace std;

long long gcd(long long a,long long b)

{

if(b == 0)return a;

return gcd(b,a%b);

}

long long lcm(long long a,long long b)

{

return a/gcd(a,b)*b;

}

struct Matrix

{

long long mat[2][2];

};

Matrix mul_M(Matrix a,Matrix b,long long mod)

{

Matrix ret;

for(int i = 0;i < 2;i++)

for(int j = 0;j < 2;j++)

{

ret.mat[i][j] = 0;

for(int k = 0;k < 2;k++)

{

ret.mat[i][j] += a.mat[i][k]*b.mat[k][j]%mod;

if(ret.mat[i][j] >= mod)ret.mat[i][j] -= mod;

}

}

return ret;

}

Matrix pow_M(Matrix a,long long n,long long mod)

{

Matrix ret;

memset(ret.mat,0,sizeof(ret.mat));

for(int i = 0;i < 2;i++)ret.mat[i][i] = 1;

Matrix tmp = a;

while(n)

{

if(n&1)ret = mul_M(ret,tmp,mod);

tmp = mul_M(tmp,tmp,mod);

n >>= 1;

}

return ret;

}

long long pow_m(long long a,long long n,long long mod)//a^b % mod

{

long long ret = 1;

long long tmp = a%mod;

while(n)

{

if(n&1)ret = ret*tmp%mod;

tmp = tmp*tmp%mod;

n >>= 1;

}

return ret;

}

//素数筛选和合数分解

const int MAXN = 1000000;

int prime[MAXN+1];

void getPrime()

{

memset(prime,0,sizeof(prime));

for(int i = 2;i <= MAXN;i++)

{

if(!prime[i])prime[++prime[0]] = i;

for(int j = 1;j <= prime[0] && prime[j] <= MAXN/i;j++)

{

prime[prime[j]*i] = 1;

if(i%prime[j] == 0)break;

}

}

}

long long factor[100][2];

int fatCnt;

int getFactors(long long x)

{

fatCnt = 0;

long long tmp = x;

for(int i = 1;prime[i] <= tmp/prime[i];i++)

{

factor[fatCnt][1] = 0;

if(tmp%prime[i] == 0)

{

factor[fatCnt][0] = prime[i];

while(tmp%prime[i] == 0)

{

factor[fatCnt][1]++;

tmp /= prime[i];

}

fatCnt++;

}

}

if(tmp != 1)

{

factor[fatCnt][0] = tmp;

factor[fatCnt++][1] = 1;

}

return fatCnt;

}

//勒让德符号

int legendre(long long a,long long p)

{

if(pow_m(a,(p-1)>>1,p) == 1)return 1;

else return -1;

}

int f0 = 1;

int f1 = 1;

long long getFib(long long n,long long mod)

{

if(mod == 1)return 0;

Matrix A;

A.mat[0][0] = 0;

A.mat[1][0] = 1;

A.mat[0][1] = 1;

A.mat[1][1] = 1;

Matrix B = pow_M(A,n,mod);

long long ret = f0*B.mat[0][0] + f1*B.mat[1][0];

return ret%mod;

}

long long fac[1000000];

long long GG[1000000];

long long G(long long p)

{

if(p < 1000000 && GG[p] != -1)return GG[p];

long long num;

if(legendre(5,p) == 1)num = p-1;

else num = 2*(p+1);

//找出num的所有约数

int cnt = 0;

for(long long i = 1;i*i <= num;i++)

if(num%i == 0)

{

fac[cnt++] = i;

if(i*i != num)

fac[cnt++] = num/i;

}

sort(fac,fac+cnt);

long long ans;

for(int i = 0;i < cnt;i++)

{

if(getFib(fac[i],p) == f0 && getFib(fac[i]+1,p) == f1)

{

ans = fac[i];

break;

}

}

if(p < 1000000)GG[p] = ans;

return ans;

}

long long find_loop(long long n)

{

getFactors(n);

long long ans = 1;

for(int i = 0;i < fatCnt;i++)

{

long long record = 1;

if(factor[i][0] == 2)record = 3;

else if(factor[i][0] == 3)record = 8;

else if(factor[i][0] == 5)record = 20;

else record = G(factor[i][0]);

for(int j = 1;j < factor[i][1];j++)

record *= factor[i][0];

ans = lcm(ans,record);

}

return ans;

}

void init()

{

getPrime();

}

int main()

{

//freopen("0.in","r",stdin);

//freopen("out.txt","w",stdout);

init();

memset(GG,-1,sizeof(GG));

int N,P;

int T;

scanf("%d",&T);

while(T--)

{

scanf("%d%d",&N,&P);

long long mod1 = P;

long long mod2 = find_loop(mod1);

long long mod3 = find_loop(mod2);

long long ans = getFib(N,mod3);

ans = getFib(ans,mod2);

ans = getFib(ans,mod1);

printf("%d\n",(int)ans);

}

return 0;

}

F:

飞行棋

解方程。 并不需要高斯消元一样去解,直接消就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* ***************

Author :kuangbin

Created Time :2014/6/23 23:37:43

File Name :E:\2014ACM\题目\Flying_chess\std.cpp

************************************************ */

#include <stdio.h>

#include <string.h>

#include <iostream>

#include <algorithm>

#include <vector>

#include <queue>

#include <set>

#include <map>

#include <string>

#include <math.h>

#include <stdlib.h>

#include <time.h>

using namespace std;

const int MAXN = 100010;

const double eps = 1e-8;

double p[MAXN][10];

double a[MAXN][10];

double x[MAXN];

int main()

{

//freopen("in.txt","r",stdin);

//freopen("out.txt","w",stdout);

int n;

while(scanf("%d",&n) == 1)

{

int d1,d2,d3,d4,d5;

memset(a,0,sizeof(a));

for(int i = 1;i <= n;i++)

x[i] = 1.0;

x[n] = 0.0;

for(int i = 1;i <= n;i++)

{

scanf("%d%d%d%d%d",&d1,&d2,&d3,&d4,&d5);

p[i][1] = (double)d1/(d1+d2+d3+d4+d5);

p[i][2] = (double)d2/(d1+d2+d3+d4+d5);

p[i][3] = (double)d3/(d1+d2+d3+d4+d5);

p[i][4] = (double)d4/(d1+d2+d3+d4+d5);

p[i][5] = (double)d5/(d1+d2+d3+d4+d5);

a[i][2] = 1.0;

for(int j = 1;j <= 5;j++)

{

int tmp = i + j - 3;

if(tmp <= 0)tmp = 1-tmp;

if(tmp > n)tmp = n - (n+1-tmp);

a[i][tmp-i+2] -= p[i][j];

}

if(i == n)

{

for(int j = 0;j < 5;j++)a[i][j] = 0.0;

a[i][2] = 1;

}

}

for(int i = n-1;i >= 1;i--)

{

for(int j = min(n,i+2);j>i;j--)

{

double tmp = a[i][j-i+2];

if(fabs(tmp) < eps)continue;

for(int k = 0;k<=2 && j-k > 0;k++)

a[i][j-k-i+2] -= a[j][2-k]*tmp;

x[i] -= x[j]*tmp;

}

double q = a[i][2];

for(int j = 0;j < 5;j++)

a[i][j] /= q;

x[i] /= q;

}

printf("%.2lf\n",x[1]);

}

return 0;

}

G:

喵喵的 Query On Tree

数据是随机的。 就是暴力搞吧。 但是DS太不人道了,数据有很大的概率出现了1. 所以要对树根,就是点1的查询,进行特殊处理。 胡搞下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/* ***************

Author :kuangbin

Created Time :2014/6/29 22:50:34

File Name :E:\2014ACM\题目\qtree.cpp

************************************************ */

#include <stdio.h>

#include <string.h>

#include <iostream>

#include <algorithm>

#include <vector>

#include <queue>

#include <set>

#include <map>

#include <string>

#include <math.h>

#include <stdlib.h>

#include <time.h>

using namespace std;

const int MAXN = 10010;

struct Edge

{

int to,next;

}edge[MAXN];

int head[MAXN],tot;

void init()

{

tot = 0;

memset(head,-1,sizeof(head));

}

void addedge(int u,int v)

{

edge[tot].to = v;

edge[tot].next = head[u];

head[u] = tot++;

}

int fa[MAXN];

int w[MAXN];

int dep[MAXN];

void dfs(int u,int d)

{

dep[u] = d;

for(int i = head[u];i != -1;i = edge[i].next)

dfs(edge[i].to,d+1);

}

int c[MAXN];

int cnt;

void dfs1(int u)

{

c[cnt++] = w[u];

for(int i = head[u];i != -1;i = edge[i].next)

dfs1(edge[i].to);

}

//适用于正负整数

template <class T>

inline bool scan_d(T &ret) {

char c; int sgn;

if(c=getchar(),c==EOF) return 0; //EOF

while(c!='-'&&(c<'0'||c>'9')) c=getchar();

sgn=(c=='-')?-1:1;

ret=(c=='-')?0:(c-'0');

while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');

ret*=sgn;

return 1;

}

inline void out(int x) {

if(x>9) out(x/10);

putchar(x%10+'0');

}

multiset<int>st;

multiset<int>::iterator it;

int main()

{

//freopen("2.in","r",stdin);

//freopen("22.out","w",stdout);

int T;

int n;

int u,v,x;

//scanf("%d",&T);

scan_d(T);

while(T--)

{

//scanf("%d",&n);

scan_d(n);

init();

st.clear();

for(int i = 1;i <= n;i++)//scanf("%d",&w[i]);

{

scan_d(w[i]);

st.insert(w[i]);

}

fa[1] = 0;

for(int i = 2;i <= n;i++)

{

//scanf("%d",&v);

scan_d(v);

addedge(v,i);

fa[i] = v;

}

dfs(1,1);

int Q;

char op[10];

scanf("%d",&Q);

while(Q--)

{

scanf("%s",op);

if(op[0] == 'C')

{

//scanf("%d%d%d",&u,&v,&x);

scan_d(u);

scan_d(v);

scan_d(x);

while(u != v)

{

if(dep[u] < dep[v])swap(u,v);

it = st.lower_bound(w[u]);

st.erase(it);

st.insert(x);

w[u] = x;

u = fa\[u\];
}
it = st.lower_bound(w\[u\]);
st.erase(it);
st.insert(x);
w\[u\] = x;
}
else
{
//scanf("%d%d",&u,&x);
scan_d(u);
scan_d(x);
if(u == 1)
{
it = st.begin();
for(int i = 0;i < n-x;i++)it++;
printf("%d\\n",*it);
continue;
}
cnt = 0;
dfs1(u);
sort(c,c+cnt);
printf("%d\\n",c\[cnt-x\]);
}
}
}
return 0;

}

H:

Driving

二分速度。 判断是否可行,然后求时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* ***************

Author :kuangbin

Created Time :2014/6/17 23:49:59

File Name :E:\2014ACM\题目\Driving\std.cpp

************************************************ */

#include <stdio.h>

#include <string.h>

#include <iostream>

#include <algorithm>

#include <vector>

#include <queue>

#include <set>

#include <map>

#include <string>

#include <math.h>

#include <stdlib.h>

#include <time.h>

using namespace std;

const int MAXN = 100010;

const double eps = 1e-8;

const double INF = 1e30;

double s[MAXN],b[MAXN];

int main()

{

//freopen("3.in","r",stdin);

//freopen("3.out","w",stdout);

int n;

double f,v;

while(scanf("%d",&n) == 1)

{

scanf("%lf%lf",&f,&v);

for(int i = 0;i < n;i++)

scanf("%lf%lf",&s[i],&b[i]);

double l = 0, r = v;

double ans = INF;

bool find = false;

while(r-l >= eps)

{

double mid = (l+r)/2;

double cost = 0;

double t = 0;

for(int i = 0;i < n;i++)

{

if(b[i] >= 0)

{

cost += (0.5*mid + b[i])*s[i];

t += s[i]/mid;

}

else

{

cost += max(0.0,0.5*mid + b[i])*s[i];

if((0.5*mid + b[i]) < eps)

t += s[i]/min(v,-b[i]/0.5);

else t += s[i]/mid;

}

}

if(cost <= f)

{

find = true;

ans = min(ans,t);

l = mid;

}

else r = mid;

}

if(!find)printf("Bad Luck!\n");

else printf("%.3lf\n",ans);

}

return 0;

}

I:

喵喵的IDE

字典树搞。 很水很暴力。 这需要对每个字典树中的点,维护最近的点在哪。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* ***************

Author :kuangbin

Created Time :2014/7/1 21:51:15

File Name :E:\2014ACM\题目\IDE.cpp

************************************************ */

#include <stdio.h>

#include <string.h>

#include <iostream>

#include <algorithm>

#include <vector>

#include <queue>

#include <set>

#include <map>

#include <string>

#include <math.h>

#include <stdlib.h>

#include <time.h>

using namespace std;

const int INF = 0x3f3f3f3f;

struct Trie

{

int next[1001000][26];

int L[1001000];

int tot,root;

int newnode()

{

for(int i = 0;i < 26;i++)

next[tot][i] = -1;

L[tot++] = INF;

return tot-1;

}

void init()

{

tot = 0;

root = newnode();

}

int insert(char buf[])

{

int len = strlen(buf);

int ans = len;

int now = root;

for(int i = 0;i < len;i++)

{

if(next[now][buf[i]-'a'] == -1)

{

next[now][buf[i]-'a'] = newnode();

now = next[now][buf[i]-'a'];

}

else

{

now = next[now][buf[i]-'a'];

ans = min(ans,1+L[now]+len-1-i);

}

L[now] = min(L[now],len-1-i);

}

return ans;

}

};

Trie tree;

char str[1000010];

int main()

{

//freopen("in.txt","r",stdin);

//freopen("out.txt","w",stdout);

int T;

int n;

scanf("%d",&T);

while(T--)

{

tree.init();

scanf("%d%s",&n,str);

tree.insert(str);

for(int i = 0;i < n;i++)

{

scanf("%s",str);

printf("%d\n",tree.insert(str));

}

}

return 0;

}

J:

Base Station

简单数据结构。 到两个基站的距离,其实就构成了二维坐标。 其中一个按照顺序加入,另外一维用一维树状数组就可以查询了。 不多说了,很水很暴力。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/* ***************

Author :kuangbin

Created Time :2014/6/25 16:17:04

File Name :E:\2014ACM\题目\Base_Station\std.cpp

************************************************ */

#include <stdio.h>

#include <string.h>

#include <iostream>

#include <algorithm>

#include <vector>

#include <queue>

#include <set>

#include <map>

#include <string>

#include <math.h>

#include <stdlib.h>

#include <time.h>

using namespace std;

int c[100010];

int lowbit(int x)

{

return x&(-x);

}

int n;

void add(int i,int val)

{

while(i <= n)

{

c[i] += val;

i += lowbit(i);

}

}

int sum(int i)

{

int s = 0;

while(i > 0)

{

s += c[i];

i -= lowbit(i);

}

return s;

}

struct Node

{

long long x,y;

}p[100010];

bool cmp(Node a,Node b)

{

return a.x > b.x;

}

struct Query

{

long long r1,r2;

int index;

}query[100010];

int ans[100010];

bool cmp2(Query a,Query b)

{

return a.r1 > b.r1;

}

long long b[100010];

int main()

{

//freopen("2.in","r",stdin);

//freopen("2.out","w",stdout);

int x1,y1,x2,y2;

int x,y;

while(scanf("%d%d%d%d",&x1,&y1,&x2,&y2) == 4)

{

scanf("%d",&n);

memset(c,0,sizeof(c));

int tot = 0;

for(int i = 0;i < n;i++)

{

scanf("%d%d",&x,&y);

long long dx1 = x1-x;

long long dy1 = y1-y;

long long dx2 = x2-x;

long long dy2 = y2-y;

long long tmp1 = dx1*dx1+dy1*dy1;

long long tmp2 = dx2*dx2+dy2*dy2;

p[i].x = tmp1;

p[i].y = tmp2;

b[++tot] = tmp2;

}

sort(p,p+n,cmp);

sort(b+1,b+tot+1);

tot = unique(b+1,b+tot+1) - b - 1;

int m;

int r1,r2;

scanf("%d",&m);

for(int i = 0;i < m;i++)

{

scanf("%d%d",&r1,&r2);

query[i].r1 = (long long)r1*r1;

query[i].r2 = (long long)r2*r2;

query[i].index = i;

}

sort(query,query+m,cmp2);

int id = 0;

for(int i = 0;i < m;i++)

{

while(id < n && p\[id\].x >= query[i].r1)

{

int loc = lower_bound(b+1,b+tot+1,p[id].y) - b;

add(loc,1);

id++;

}

int L = lower_bound(b+1,b+tot+1,query[i].r2) - b;

ans[query[i].index] = sum(n) - sum(L-1);

}

for(int i = 0;i < m;i++)

printf("%d\n",ans[i]);

}

return 0;

}
------ 本文结束------
  • 本文作者: kuangbin
  • 本文链接: 212.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
0%