CF492E Vanya and Field
Posted mrclr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF492E Vanya and Field相关的知识,希望对你有一定的参考价值。
题目大意:
一天,Vanya 来到了一片滑稽树林中,准备采摘滑稽果。滑稽树林可看作一个 n×n 的正方形,其中 m 个点上有滑稽果,某些点没有。(注意一个点上可能有多个滑稽果)
Vanya会沿向量 (dx,dy)(dx,dy) 方向移动。也就是说,如果Vanya在 (x,y) 处,她将移动到 ((x+dx) mod n,(y+dy) mod n)((x+dx) mod n,(y+dy) mod n) 处。每到一个点,她会拿走该点所有滑稽果。(dx,dy 为定值(输入中给出),且 gcd(n,dx)=gcd(n,dy)=1)
由于滑稽树林太巨了,当Vanya走到一个她走到过的点时,她就会停止走动。
现在Vanya想知道她怎么走才能拿到最多的滑稽果。
(来自巨佬interestinLSY的翻译)
啊对了,n<= 10 ^ 5。
可见暴力不行呐
容易证明,(x, y)点在移动n次一定会回到原点,即每一条路线的移动周期是n。而且可以得出,在这个移动周期内,每一个点x, y 分别对n取模得到的值都不相同,也就是说,一条路线内每个点横纵坐标两两不相同。
那么我们只要求出每一个有果子的点属于哪一条路线就可以了。
首先可以随意选一条路线(为了方便,称为基线),将他的每一个点求出来,得到一个y已知时x的映射,而且上文已经说道,对于每一个0 <= y < n,都有唯一的x与之对应。
求出一条路线后,其他路线就可以由基线平移得到,所以对于每一个有果子的点,只要求出他和基线上y相同的点的距离,即第几条路线,然后开一个类似桶的数组记录每一条路线收获的果子数量,答案取max即可。
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<stack> 9 #include<queue> 10 #include<vector> 11 using namespace std; 12 #define enter printf(" ") 13 #define space printf(" ") 14 #define Mem(a) memset(a, 0, sizeof(a)) 15 typedef long long ll; 16 typedef double db; 17 const int INF = 0x3f3f3f3f; 18 const db eps = 1e-8; 19 const int maxn = 1e6 + 5; 20 inline ll read() 21 { 22 ll ans = 0; 23 char ch = getchar(), last = ‘ ‘; 24 while(!isdigit(ch)) {last = ch; ch = getchar();} 25 while(isdigit(ch)) 26 { 27 ans = ans * 10 + ch - ‘0‘; ch = getchar(); 28 } 29 if(last == ‘-‘) ans = -ans; 30 return ans; 31 } 32 inline void write(ll x) 33 { 34 if(x < 0) x = -x, putchar(‘-‘); 35 if(x >= 10) write(x / 10); 36 putchar(x % 10 + ‘0‘); 37 } 38 39 int n, m, dx, dy; 40 41 int a[maxn], b[maxn], ans = 0, pos; 42 int pnt[2][maxn]; 43 44 int main() 45 { 46 n = read(); m = read(); dx = read(); dy = read(); 47 for(register int i = 0, j = 1; j < n; i = (i + dy) % n, ++j) //求基线 48 a[(i + dy) % n] = (a[i] + dx) % n; 49 for(register int i = 1; i <= m; ++i) 50 { 51 int x = read(), y = read(), t; 52 t = (x - a[y] + n) % n; //算距离 53 b[t]++; 54 pnt[0][t] = x; pnt[1][t] = y; //第t条路线一定经过的点就是(x, y) 55 } 56 for(register int i = 0; i < n; ++i) 57 if(b[i] > ans) {ans = b[i]; pos = i;} 58 write(pnt[0][pos]); space; write(pnt[1][pos]); enter; 59 return 0; 60 }
以上是关于CF492E Vanya and Field的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces - 552C Vanya and Scales
B. Vanya and Lanterns1200 / 贪心 二分
codeforce 677D Vanya and Treasure
Codeforces 677D - Vanya and Treasure