Codeforces Round #280 (Div. 2) D:二分+浮点数模型转为整型模型 E:数学(取模)

比赛地址:

http://codeforces.com/contest/492


官方题解:

Codeforces Round #280 (Div. 2) Editorial

By  Wild_Hamster,  11 hours ago, translation,  , 

492A - Vanya and Cubes.

In fact need to do what is asked in the statement. We need to find in a cycle the maximum height h, counting, how many blocks must be in i-th row and adding these values to the result. Iterate until the result is not greater than n.

Jury's solution: 8924831

492B - Vanya and Lanterns.

Sort lanterns in non-decreasing order. Then we need to find maximal distance between two neighbour lanterns, let it be maxdist. Also we need to consider street bounds and count distances from outside lanterns to street bounds, it will be (a[0] - 0) and (l - a[n - 1]). The answer will be max(maxdist / 2, max(a[0] - 0, l - a[n - 1]))

Time complexity O(nlogn).

Jury's solution: 8924823

492C - Vanya and Exams.

Sort (ai, bi) in non-decreasing order for number of essays bi, after that go from the beginning of this sorted pairs and add greedily the maximal number of points we can, i.e. add value min(avg * n - sum, r - ai), while total amount of points will not be greater, than avg * n.

Time complexity O(nlogn).

Jury's solution: 8924807

492D - Vanya and Computer Game.

Let's create vector rez with size x + y, in which there will be a sequence of Vanya's and Vova's strikes for the first second. To do this, we can take 2 variables cntx = cnty = 0. Then while cntx < x and cnty < y, we will check 3 conditions:

1) If (cntx + 1) / x > (cnty + 1) / y, then add into the vector word “Vova”, cnty++.

2) If (cntx + 1) / x < (cnty + 1) / y, then add into the vector word “Vanya”, cntx++.

3) If (cntx + 1) / x = (cnty + 1) / y, then add into the vector word “Both” 2 times, cntx++, cnty++.

Then we are able to respond on each query for О(1), the answer will be rez[(ai - 1)mod(x + y)].

Time complexity O(x + y).

Jury's solution: 8924773

492E - Vanya and Field.

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, where1 - 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 kfor О(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).

Jury's solution: 8924746

P.S. Sorry for my bad English, I hope, I will correct this editorial as much, as possible.


D题:

题意是两个人一起打怪兽,怪兽被打a次就会死去,第一个人每单位时间打x次,第二个人每单位时间打y次,频率都是稳定的,问怪兽死前被谁打的最后一下。

二分怪物死去时的时间是最简单的想法,但是这里的时间是浮点型,所以转换一下:

二分时间,算打击次数>=a,然后看当前时间谁出手了。
原题等价成1每y单位时间打击一次,2每x单位时间打击一次,避免小数问题。

方法二:

二分1打击次数的方法,判断1打最后一下而2没打最后一下是否成立;

2同理;都成立的情况就是Both。

方法三:

打表算出打第i下是1还是2打的,最后再查表。


E题:

n*n的格子,m棵树的坐标告诉了你,要你选择一个坐标作为起点,每次的移动向量是(dx,dy),落点取模计算:x=(x+dx)%n,y=(y+dy)%n,通过最多课果树。

因为题目告诉了gcd(n,dx)=1,gcd(n,dy)=1,所以从起点出发到回到起点必然是n步,n是10^6的,所以可以把n*n个格子分为分别从(0,0),(0,1),(0,2)...(0,n-1)出发可达的n个集合。对于每个集合其实走的路线都是一样的,所以可以保存从(0,0)出发可达的格子的坐标,再通过计算横向的偏移量来计算是从(0,0),(0,1),(0,2)...(0,n-1)里哪一个出发的,就知道属于哪个集合。统计一遍输出答案。


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1111111;
int a[maxn],b[maxn];
int main()
{
    int n,m,dx,dy,x,y;
    scanf("%d%d%d%d",&n,&m,&dx,&dy);
    x=0,y=0;
    a[0]=0;
    for(int i=0;i<n;i++){
        x=(x+dx)%n;
        y=(y+dy)%n;
        a[x]=y;
    }
    for(int i=0;i<m;i++){
        scanf("%d%d",&x,&y);
        b[(y-a[x]+n)%n]++;
    }
    int ans=0,j=0;
    for(int i=0;i<n;i++){
        if(b[i]>j){
            ans=i;
            j=b[i];
        }
    }
    printf("0 %d\n",ans);

    return 0;
}





你可能感兴趣的:(codeforces,二分,取模)