题目描述:http://codeforces.com/problemset/problem/492/E
(英文题)翻译不写了大家都能看懂。
看到这道题的第一想法是啥……?暴力模拟?其实这题似乎还真的可以暴力模拟,不过要选对模拟的方法。首先我们看,因为dx,dy都与n互质,我们用那么我们以dx为例,就可以知道dx*0,dx*1,dx*2……dx*(n-1)这些数mod n所得的余数都不同,而且恰好构成了一个完全剩余系,同理dy也是。这样我们就可以得知,一个人最多走n步就会走到原来走过的位置,就会停下。而且在这n步之内,每一步的终点,其横纵坐标都是唯一的,且这些终点恰好取遍了横轴和纵轴。而其他路径就可以看做是由一条路径上下平移而成。
这样我们就差不多明白了,相当于一共只有n条路径,这些路径恰好取满了整个区域,没有重叠和遗漏。既然如此我们就可以开始暴力模拟了。不过直接去模拟计算每条路径上的权值之和显然是不行的,那么我们倒过来想,枚举树所在的节点属于哪条路径就可以了!我们可以选择以(0,0)点为起点的路径为基准,先处理出来这条路径上,每个终点的坐标。之后因为其他路径都可以看做由这条路径平移而成,所以直接计算一下树和路径之间的距离也就知道这棵树是属于哪条路径的了。
有一些很神奇的实现方法qwq(也没多神奇)。然后因为这题有spj嘛,所以直接输出路径上第一个终点的坐标就行。(即横坐标为0,方便嘛)
看一下代码。
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar(' ') using namespace std; typedef long long ll; const ll INF = 1e9; const int M = 1000005; ll read() { ll ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } int n,m,dx,dy,route[M],a[M],x,y,cur,maxn = -1,pos = -1; int main() { n = read(),m = read(),dx = read(),dy = read(); a[0] = 0; rep(i,2,n) { a[(cur+dx)%n] = (a[cur] + dy) % n; cur = (cur + dx) % n; }//优先处理出起点为(0,0)的路径的各个终点的位置 rep(i,1,m) { x = read(),y = read(); if(y >= a[x]) route[y-a[x]]++;//route[i]记录一条路径上的苹果树个数 else route[n-a[x]+y]++; }//分在上面还是下面,如果在上面需要反着算一下 rep(i,0,n-1) if(route[i] > maxn) maxn = route[i],pos = i; printf("%d %d",0,pos); return 0; }