1. 程式人生 > >Codeforces Round #280 (Div. 2) D:二分+浮點數模型轉為整型模型 E:數學(取模)

Codeforces Round #280 (Div. 2) D:二分+浮點數模型轉為整型模型 E:數學(取模)

比賽地址:

http://codeforces.com/contest/492

官方題解:

Codeforces Round #280 (Div. 2) Editorial

By Wild_Hamster11 hours ago, translation, In English

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

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

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

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

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;
}