zoukankan      html  css  js  c++  java
  • 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+dxmon,(y+dymon) 处。每到一个点,她会拿走该点所有滑稽果。(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 }
  • 相关阅读:
    取一定范围的随机数
    小菜学Chromium之OpenGL学习之二
    程序员健康之路
    解密硬件解码关键技术
    Android 图片开发内幕系列第一篇
    你所不知道的html5与html中的那些事第三篇
    如何加密android apk
    linux设备驱动第五篇:驱动中的并发与竟态
    快速调试chromium
    小菜鸟带着梦想学chromium
  • 原文地址:https://www.cnblogs.com/mrclr/p/9434024.html
Copyright © 2011-2022 走看看