Блог пользователя chokudai

Автор chokudai, история, 6 лет назад, По-английски

We will hold AtCoder Beginner Contest 191.

The point values will be 100-200-300-400-500-600.

We are looking forward to your participation!

  • Проголосовать: нравится
  • +6
  • Проголосовать: не нравится

»
6 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится +5 Проголосовать: не нравится

I will record a screencast and an editorial and publish them on my YT channel shortly after the contest. Screencast will be here once processed, and there won't be an editorial because I don't want to look at these problems ever again.

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +82 Проголосовать: не нравится

Geometry... XO

  • »
    »
    6 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +18 Проголосовать: не нравится

    44 and 2 for me

  • »
    »
    6 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
  • »
    »
    6 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +3 Проголосовать: не нравится
    Relatable :P
  • »
    »
    6 лет назад, скрыть # ^ |
    Rev. 2  
    Проголосовать: нравится -30 Проголосовать: не нравится

    Here is my solution below which I came up after contest. In general, the key for AC is to translate the entire problem to discrete space by multiplying input by 10000. Moreover, even after multiplying long double by 10000, you can not just assign it to int64_t. You should use llroundl instead.

    #include <bits/stdc++.h>
    using namespace std;
    
    using lli = int64_t;
    using ld = long double;
    
    lli g = 10000;
    
    lli dist(lli x1, lli y1, lli x2, lli y2)
    {
        return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
    }
    
    lli bsearch(lli x, lli y, lli r, lli y1, lli l, lli h, bool fl)
    {
        lli ans = LLONG_MAX;
    
        while (l <= h)
        {
            lli mid = l + (h - l) / 2;
            mid -= mid % g;
    
            if (dist(x, y, mid, y1) <= r * r)
            {
                ans = mid;
    
                (fl ? l : h) = mid + (fl ? g : -g);
            }
            else
                (fl ? h : l) = mid + (fl ? -g : g);
        }
    
        return ans;
    }
    
    lli calc(lli x, lli y, lli r, lli y1)
    {
        lli rx = x;
        rx -= rx % g;
    
        lli mid = LLONG_MAX;
    
        if (dist(x, y, rx, y1) <= r * r)
            mid = rx;
        else
        if (dist(x, y, rx + g, y1) <= r * r)
            mid = rx + g;
    
        if (mid == LLONG_MAX) return 0;
    
        lli rl = x - r;
        lli rr = x + r;
    
        rl -= rl % g;
        rr -= rr % g;
        rr += g;
    
        lli l = bsearch(x, y, r, y1, rl, mid, false);
        lli h = bsearch(x, y, r, y1, mid, rr, true);
    
        return (h - l) / g + 1;
    }
    
    int main()
    {
        ios_base::sync_with_stdio(false);
        cin.tie(nullptr);
    
        ld xd, yd, rd; cin >> xd >> yd >> rd;
        
        lli x = llroundl(xd * ld(g));
        lli y = llroundl(yd * ld(g));
        lli r = llroundl(rd * ld(g));
    
        lli ans = 0;
    
        for (lli y1 = y - y % g; y - y1 <= r; y1 -= g)
            ans += calc(x, y, r, y1);
    
        for (lli y1 = y - (y % g) + g; y1 - y <= r; y1 += g)
            ans += calc(x, y, r, y1);
    
        cout << ans << endl;
        return 0;
    }
    
»
6 лет назад, скрыть # |
 
Проголосовать: нравится +140 Проголосовать: не нравится

I hope whoever set today's contest doesn't set any Atcoder Beginner Contests for a while...

»
6 лет назад, скрыть # |
Rev. 3  
Проголосовать: нравится +22 Проголосовать: не нравится

How to solve C ? Please also explain the problem statement (maybe by taking few examples) .

  • »
    »
    6 лет назад, скрыть # ^ |
    Rev. 3  
    Проголосовать: нравится +1 Проголосовать: не нравится

    iterate in normal fashion, but maintain whether for previous cell you have considered a side or not. So let me show an example:

    .....
    .#.#.
    .###.
    .....
    
    

    Here, there are 8 sides. We maintain for each cell, whether we have considered white cell that is $$$L, R, U, D$$$ to it. So for black cell at $$$(1,1)$$$, we have white cell at left, therefore for black cell $$$(2, 1)$$$ we will not consider left white cell as a side.

    Example image
  • »
    »
    6 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    You will just have to know one thing that you have new side in left if the one above you doesn't have side in left and same if for right . And you have a side above if one to left of you doesn't have a side above you and same for down . JUST traverse the array and do the above mentioned operation .

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +56 Проголосовать: не нравится

What was the point of setting X, Y and R to real numbers instead of integers? It's useless complications and I'm sure many contestants solved the problem but did not get accepted because of precision issues

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +7 Проголосовать: не нравится

C and D were quite tough

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +62 Проголосовать: не нравится

Huge thanks to ABCs for letting me become sooooooo aware of floating point errors! I was never so afraid of them before.

»
6 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

Anyone else getting TLE for 1 test case using Djikstra on E!? https://atcoder.jp/contests/abc191/submissions/20001075 my code

»
6 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

How do you guys who got ac deal with decimal precisions in D?

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +4 Проголосовать: не нравится

Unfortunately C with low quality. The selection for D was doubtful last week. I hope we will get back to usual quality soon.

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +67 Проголосовать: не нравится

I don't like D. In my opinion, it does not fit the other AtCoder's values that I noticed in other contests.

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +8 Проголосовать: не нравится

520 pages of D WA

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится

Why there isn't any pop-up(prompt) on the screen in Atcoder if there is any correction or anything? It is there in the codeforces and even in Atcoder(but only when the contest ends).

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится

I spent a lot of time trying to decipher the problem statement of problem C and...still have no idea what I'm supposed to do.

  • »
    »
    6 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    I understand it from this announced clarification:

    Please consider that square (i, j) occupies the region consisting of the points satisfying i — 1 <= x <= i and j — 1 <= y <= j. For a white square and a black square that are adjacent to each other, we consider the boundary between them to be painted black.

    The phrase "Consider the part of the grid that is painted black as a polygon" means we consider the polygon such that its interior, including the circumference, matches the part painted black.

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится

Ok! that's enough geometry for few months atleast.

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +25 Проголосовать: не нравится

How to handle precision issues in D , I have made 18 wa penalties in D still getting wa on a single test case out of 46 ... :(

  • »
    »
    6 лет назад, скрыть # ^ |
    Rev. 2  
    Проголосовать: нравится +13 Проголосовать: не нравится

    Multiply input values by 10^4 and do everything in long long. Here's a submission that works (unfortunately after contest T_T).

    • »
      »
      »
      6 лет назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится

      Is there somewhere I can see the test cases?

      Why does this fail on some cases?
  • »
    »
    6 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    Similar case this side.

    Looking at the stats for problem D (29 pages of AC, while 565 pages of WA) many faced the same situation :/ Precision > Accuracy XD

  • »
    »
    6 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    Tweak your epsilon until it passes

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +2 Проголосовать: не нравится

How to solve B?

»
6 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

How to solve E? I used dijkstra and it was pretty bad complexity, failed with TLE and also WA.

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +5 Проголосовать: не нравится

How to approach for problem C ?

»
6 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Today I learnt how to parse 5 digits + 4 decimals :D

»
6 лет назад, скрыть # |
Rev. 3  
Проголосовать: нравится +1 Проголосовать: не нравится
Sad :(
»
6 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

God knows when will I learn to handle doubles ;( Can anybody help where might be precision errors in my Solution, I got 2 WA constantly.

»
6 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

A, B, C, E : soso

D : get f**ked by precision issues

F : didn't get to see it after 10 WA @ D

(still getting WA on D btw sending HELP)

»
6 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

I cant find test cases after ABC 188. When will it be uploaded?

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +21 Проголосовать: не нравится

How to solve F?

  • »
    »
    6 лет назад, скрыть # ^ |
    Rev. 3  
    Проголосовать: нравится +45 Проголосовать: не нравится

    Observation #1: Any number resulting in the end should be less or equal to the current minimum.

    Observation #2: At any given time we can discard all elements of the current list and keep the minimum.

    You should see now that the answer to the problem is the number of distinct GCD's we can get from subsets the initial array, that are less than the current minimum.

    Generate all divisors of every number in $$$O(n\sqrt{n})$$$ and then save every divisor less or equal to the minimum of the array. Then, for each such divisor, check if the gcd of all its multiples in the array is equal to it. If so increment the answer.

    We like to assume that each number has roughly $$$O(\log n)$$$ divisors so we'll find at most $$$O(n\log A)$$$ such divisors where A is the max number in the array

    Complexity: $$$O(n^2\log A)$$$ where A is the max number in the array

    • »
      »
      »
      6 лет назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится

      "We like to assume that each number has roughly O(logn) divisors so we'll find at most O(nlogA) such divisors where A is the max number in the array"

      Can you please explain why we assume that each number has roughly O(logn) divisors? (we are counting only those divisors that are less or equal to the minimum of the array? And why would that be O(logn))?

»
6 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

.....

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +5 Проголосовать: не нравится
»
6 лет назад, скрыть # |
 
Проголосовать: нравится +8 Проголосовать: не нравится

I tried to solve D but got 3 WA. Here is the submission. Then I found that my solution was very similar to the earliest submission made by one of the writers. The only differences between the two solutions were the first one (my submission) used double but the second one used long double, and the second one used nextafter() but the first one didn't. I changed double to long double but still got 2 WA (and the wrong test cases were different, click here to see it). I added nextafter() to my solution so that I got AC (click here to see it). Then I changed back from long double to double and I still got 4 WA (and the wrong test cases were also different, click here to see it). Can someone please explain the effect of the function nextafter() and why I got WA? Or can you please give me a test case that can make my first solution wrong? Thanks so much!

  • »
    »
    6 лет назад, скрыть # ^ |
    Rev. 3  
    Проголосовать: нравится 0 Проголосовать: не нравится

    Try:

    36.0 13.2 40.8 (Answer should be 5222)

    24.0 29.2 13.2 (Answer should be 549)

    If you discover what the problem is let me know, my solution using long longs has the same problem, but it works with long double and nextafter. The problem in my case are usually when X coordinate is already a integer (double counting) but I couldn't fix it. (If there is a point which is exactly x^2+(y-yc)^2 == r^2 and X coordinate is integer).

    EDIT: My AC code was incorrect (output was 548 for case 2)

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +8 Проголосовать: не нравится
»
6 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

So regarding D I have the following dummy "solution":

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
#define FOR(i, j, k, in) for (ll i = j; i < k; i += in)
#define RFOR(i, j, k, in) for (ll i = j; i >= k; i -= in)
#define REP(i, j) FOR(i, 0, j, 1)
#define RREP(i, j) RFOR(i, j, 0, 1)

ll dist(ll cx, ll cy, ll x, ll y) {
    return (cx - x) * (cx - x) + (cy - y) * (cy - y);
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    ll multi = 10000;
    ld tx, ty, tr;
    cin >> tx >> ty >> tr;
    ll x = (ll)(tx * (ld)multi), y = (ll)(ty * (ld)multi), r = (ll)(tr * (ld)multi);
    ll r2 = r * r;

    ll xlow = x - r;
    xlow -= xlow % multi;
    ll xhigh = x + r;
    xhigh += multi - xhigh % multi;
    ll ylow = y - r;
    ylow -= ylow % multi;
    ll yhigh = y + r;
    yhigh += multi - yhigh % multi;

    ll total = 0;
    FOR(i, xlow, xhigh + multi, multi) {
        FOR(j, ylow, yhigh + multi, multi) {
            if (dist(i, j, x, y) <= r2) total++;
        }
    }
    cout << total << endl;
    return 0;
}

What's odd about this is that it differs from accepted solutions of the problem on various inputs like "9646.9314 4394.792 6719.9786". I think that's bad since the code above obviously solves the problem. My assumption is that some of the test cases contain one off errors due to numerical instability of the calculations which can happen with floating point numbers but not with integers.

Am I missing something here or is this really an issue?

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +11 Проголосовать: не нравится

I spent quite some time trying to upsolve D. After downloading some of the AC solutions and generating random cases against mine, it turns out I got WA in a few random cases because of not using round when converting the radius to integer.

I'm still not sure, why is it needed? For example:

#include <cstdio>
#include <cmath>
using namespace std;

int main() {
  double r = 313.9385;
  printf("%.6lf\n", r*10000);                   // ok, prints 3139385.000000
  printf("%lld\n", (long long)round(r*10000));  // ok, prints 3139385
  printf("%lld\n", (long long)(r*10000));       // ??, prints 3139384
  return 0;
}

For context, here's the accepted solution: https://atcoder.jp/contests/abc191/submissions/20017357.

  • »
    »
    6 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    OK, rubber duck: I guess it's because "313.9385" is not actually representable in double :(

    • »
      »
      »
      6 лет назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится

      I'm still not sure I understand how does rounding help with that. Also how did you find out that it's not representable as a double?

      • »
        »
        »
        »
        6 лет назад, скрыть # ^ |
         
        Проголосовать: нравится +3 Проголосовать: не нравится

        I'm still not sure I understand how does rounding help with that.

        The way I understand it, since the exact value cannot be represented, the value stored is less than what you actually want (something like 313.9384XXX...). You can verify this by printing the result with more decimal points. For example, using "%.18lf" outputs 313.938499999999976353. Thus, the radius you read is actually less than the intended. Multiplying that by a (representable) scale value doesn't really help, since you are still chopping that last digit when keeping the integer part with a simple cast.

        If the value is representable in first place, round has no effect, because after you multiply by the representable scale, the resulting value is representable and guaranteed to be an integer since the problem says no more than 4 decimal digits. (Example: "313.9384" is representable and round(313.9384 * 10000) == round(3139384.0) == 3139384).

        If the value is not representable, then round will change it towards the closest representable integer. (Example: "313.9385" is not representable and round(313.938499999999976353 * 10000) == round(3139384.99999999976353) == 3139385). This keeps the original value in the scaled context.

        Probably other things work as well, such as adding a small epsilon which would not change the values in the scaled context but would have the same effect as rounding towards the nearest integer.

        Also how did you find out that it's not representable as a double?

          string s = "313.9385";
          double x = stod(s);
          cout << (fetestexcept(FE_INEXACT) ? "inexact" : "exact") << '\n';
          printf("%.18lf\n", x * 10000);
        
          // inexact
          // 3139384.999999999534338713
        
        • »
          »
          »
          »
          »
          6 лет назад, скрыть # ^ |
           
          Проголосовать: нравится +3 Проголосовать: не нравится

          Thanks for the detailed explanation!

          For some reason I naively thought that when one converts to an integer type from a floating point type there is a rounding happening there. Apparently the fractional part gets chopped off and that's it.

          I didn't even know about "fetestexcept" or the existence of the "FE_INEXACT" flag. Nice job debugging this!

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +5 Проголосовать: не нравится

Why does adding 1e-14 to the value of r after taking input, removes the precision errors? What concept is this?

»
6 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

can someone please help me out with problem E, i am getting tle in 6 cases,but my logic seems to be n^2*log(n), like I am doing dijkstra for every node . Here is my submission link(i have made my code clear and easy to read) submission.

»
6 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится +10 Проголосовать: не нравится

Words hiding behind each problem

A
B
C
D
E
F
»
6 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

I am always getting WA of the test cases "handmade_marginal_00.txt" and "handmade_marginal_04.txt" for Prob D. Is there anyone who also had faced the problem and knows how to fix the code?

»
6 лет назад, скрыть # |
 
Проголосовать: нравится +4 Проголосовать: не нравится

I attempted the problems after the contest (solving A-E), and uploaded my stream here: https://youtu.be/d5FaKqYwLzY

In particular, I implemented D without floating-point numbers, which may be of interest.

»
6 лет назад, скрыть # |
Rev. 7  
Проголосовать: нравится 0 Проголосовать: не нравится

Could some one please help in figuring out the mistake in my code in problem D . I have used binary search method and i have multiplied all the input values to $$$10^4$$$ . It's giving WA on 5 test cases .

UPD : I found my mistake . Don't forget to parse the input i.e try to read it in a way so that there is no precision loss . For example 77706.2925 is stored as 77706.29249999 and if you don't take rounding then it will be stored as 777062924 after multiplying with 1e4. Whereas if you do rounding as given in following spoiler , it will be stored as 777062925.

Spoiler