Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8b3f7f7

Browse files
committed
ABC284-D
1 parent 6bbc142 commit 8b3f7f7

File tree

9 files changed

+314
-0
lines changed

9 files changed

+314
-0
lines changed

‎README.md‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,3 +386,16 @@ Haskellで競技プログラミングをやるテクニックは「[Haskellで
386386
* [ ] B - メタ構文変数
387387
* [ ] C - データ構造
388388
* [x] D - 見たことのない多項式
389+
390+
## AtCoder Beginner Contest 284
391+
392+
<https://atcoder.jp/contests/abc284>
393+
394+
* [ ] A - Sequence of Strings
395+
* [ ] B - Multi Test Cases
396+
* [ ] C - Count Connected Components
397+
* [x] D - Happy New Year 2023
398+
* [ ] E - Count Simple Paths
399+
* [ ] F - ABCBAC
400+
* [ ] G - Only Once
401+
* [ ] Ex - Count Unlabeled Graphs

‎abc/abc284-d/Main.hs‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
-- https://github.com/minoki/my-atcoder-solutions
2+
{-# LANGUAGE TypeApplications #-}
3+
{-# LANGUAGE BangPatterns #-}
4+
import Data.Int (Int64)
5+
import Control.Monad
6+
import qualified Data.Vector.Unboxed as U
7+
import qualified Data.Vector.Unboxed.Mutable as UM
8+
9+
{-
10+
-- i <= 4.5 * 10^18
11+
integerSquareRoot :: Int64 -> Int64
12+
integerSquareRoot i = loop 2 2121320343
13+
where loop !low !high | low == high = low
14+
| otherwise = let !mid = (low + high) `quot` 2
15+
!mid2 = mid * mid
16+
in case compare i mid2 of
17+
LT -> loop low mid
18+
EQ -> mid
19+
GT -> loop mid high
20+
-}
21+
integerSquareRoot :: Int64 -> Int64
22+
integerSquareRoot = round . sqrt . fromIntegral
23+
24+
solve :: [Int64] -> Int64 -> (Int64, Int64)
25+
solve primes !n = case [(p,m) | p <- primes, (m,0) <- [n `quotRem` p]] of
26+
[] -> error "No prime factor found"
27+
(p,m):_ -> if m `rem` p == 0 then
28+
(p, m `quot` p)
29+
else
30+
-- m <= 4.5 * 10^18
31+
(integerSquareRoot m, p)
32+
33+
main = do
34+
t <- readLn @Int
35+
tests <- U.replicateM t $ readLn @Int64
36+
let !primes = sieve 2080083 -- 2080083^3 < 9*10^18 < 2080084^3
37+
U.forM_ tests $ \t -> do
38+
let (p, q) = solve primes t
39+
putStrLn $ show p ++ " " ++ show q
40+
41+
--
42+
-- Sieve of Eratosthenes
43+
--
44+
45+
infixr 5 !:
46+
(!:) :: a -> [a] -> [a]
47+
(!x) !: xs = x : xs
48+
49+
-- | エラトステネスの篩により、 max 以下の素数の一覧を構築して返す
50+
-- >>> sieve 100
51+
-- [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
52+
sieve :: Int -> [Int64]
53+
sieve !max = 2 : U.ifoldr (\i isPrime xs -> if isPrime then fromIntegral (2 * i + 1) !: xs else xs) [] vec
54+
where
55+
vec = U.create $ do
56+
vec <- UM.replicate ((max - 1) `quot` 2 + 1) True
57+
UM.write vec 0 False -- 1 is not a prime
58+
-- vec ! i : is (2 * i + 1) prime?
59+
let clear !p = forM_ [3*p,5*p..max] $ \n -> UM.write vec (n `quot` 2) False
60+
factorBound = floor (sqrt (fromIntegral max) :: Double)
61+
loop !i | 2 * i + 1 > factorBound = return ()
62+
| otherwise = do b <- UM.read vec i
63+
when b $ clear (2 * i + 1)
64+
loop (i + 1)
65+
loop 1
66+
return vec

‎abc/abc284-d/Search.hs‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import Data.Int (Int64)
2+
import qualified Test.QuickCheck as QC
3+
import Math.NumberTheory.Primes
4+
5+
test :: Int64 -> Bool
6+
test n = truncate (sqrt (fromIntegral (n^2 :: Int64) :: Double)) < n
7+
8+
examples :: [Int64]
9+
examples = [a | p <- [nextPrime 94906266..precPrime 3037000499], let a = fromInteger (unPrime p), test a]
10+
11+
prop :: QC.Property
12+
prop = let gen = QC.choose (94906266, 3037000499) -- 94906265^2 < 2^53 < 94906266^2, 3037000499^2 < 2^63 - 1 < 3037000500^2
13+
in QC.forAll gen (\n -> truncate (fromIntegral (n^2 :: Int64) :: Double) < n^2)
14+
15+
-- main = QC.quickCheck prop
16+
17+
main = print $ take 10 [n | n <- [94906266..3037000499], test n]
18+
19+
-- main = print examples

‎abc/abc284-d/main-binarysearch.c‎

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include <inttypes.h>
2+
#include <math.h>
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
6+
// 入力:n <= 4.5*10^18, nは平方数
7+
int64_t isqrt(int64_t n)
8+
{
9+
// 4.5*10^18 < 2^62
10+
// 真の答えは 2 <= _ < 2^31 の範囲にある
11+
int64_t low = 2, high = INT64_C(1) << 31;
12+
while (low < high) {
13+
int64_t mid = (low + high) / 2;
14+
int64_t mid2 = mid * mid;
15+
if (mid2 < n) {
16+
low = mid;
17+
} else if (mid2 == n) {
18+
return mid;
19+
} else {
20+
high = mid;
21+
}
22+
}
23+
return low;
24+
}
25+
26+
struct result {
27+
int64_t p, q;
28+
};
29+
30+
// 入力:N <= 9*10^18
31+
struct result solve(int64_t N)
32+
{
33+
// 2080083^3 < 9*10^18 < 2080084^3
34+
for (int64_t a = 2; a <= 2080083; ++a) {
35+
if (N % a == 0) {
36+
int64_t b = N / a;
37+
if (b % a == 0) {
38+
// a = p
39+
return (struct result){.p = a, .q = b / a};
40+
} else {
41+
// a = q
42+
return (struct result){.p = isqrt(b), .q = a};
43+
}
44+
}
45+
}
46+
abort();
47+
}
48+
49+
int main()
50+
{
51+
int T;
52+
scanf("%d", &T);
53+
for (int i = 0; i < T; ++i) {
54+
int64_t N;
55+
scanf("%" SCNd64, &N);
56+
struct result r = solve(N);
57+
printf("%" PRId64 " %" PRId64 "\n", r.p, r.q);
58+
}
59+
}

‎abc/abc284-d/main-longdouble.c‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include <assert.h>
2+
#include <float.h>
3+
#include <inttypes.h>
4+
#include <math.h>
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
8+
static_assert(LDBL_MANT_DIG >= 64, "not enough precision");
9+
10+
// 入力:n <= 4.5*10^18, nは平方数
11+
int64_t isqrt(int64_t n)
12+
{
13+
return (int64_t)sqrtl((long double)n);
14+
}
15+
16+
struct result {
17+
int64_t p, q;
18+
};
19+
20+
// 入力:N <= 9*10^18
21+
struct result solve(int64_t N)
22+
{
23+
// 2080083^3 < 9*10^18 < 2080084^3
24+
for (int64_t a = 2; a <= 2080083; ++a) {
25+
if (N % a == 0) {
26+
int64_t b = N / a;
27+
if (b % a == 0) {
28+
// a = p
29+
return (struct result){.p = a, .q = b / a};
30+
} else {
31+
// a = q
32+
return (struct result){.p = isqrt(b), .q = a};
33+
}
34+
}
35+
}
36+
abort();
37+
}
38+
39+
int main()
40+
{
41+
int T;
42+
scanf("%d", &T);
43+
for (int i = 0; i < T; ++i) {
44+
int64_t N;
45+
scanf("%" SCNd64, &N);
46+
struct result r = solve(N);
47+
printf("%" PRId64 " %" PRId64 "\n", r.p, r.q);
48+
}
49+
}

‎abc/abc284-d/main-round.c‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include <inttypes.h>
2+
#include <math.h>
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
6+
// 入力:n <= 4.5*10^18, nは平方数
7+
int64_t isqrt(int64_t n)
8+
{
9+
return llround(sqrt((double)n));
10+
}
11+
12+
struct result {
13+
int64_t p, q;
14+
};
15+
16+
// 入力:N <= 9*10^18
17+
struct result solve(int64_t N)
18+
{
19+
// 2080083^3 < 9*10^18 < 2080084^3
20+
for (int64_t a = 2; a <= 2080083; ++a) {
21+
if (N % a == 0) {
22+
int64_t b = N / a;
23+
if (b % a == 0) {
24+
// a = p
25+
return (struct result){.p = a, .q = b / a};
26+
} else {
27+
// a = q
28+
return (struct result){.p = isqrt(b), .q = a};
29+
}
30+
}
31+
}
32+
abort();
33+
}
34+
35+
int main()
36+
{
37+
int T;
38+
scanf("%d", &T);
39+
for (int i = 0; i < T; ++i) {
40+
int64_t N;
41+
scanf("%" SCNd64, &N);
42+
struct result r = solve(N);
43+
printf("%" PRId64 " %" PRId64 "\n", r.p, r.q);
44+
}
45+
}

‎abc/abc284-d/main-trunc.c‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include <inttypes.h>
2+
#include <math.h>
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
6+
// 入力:n <= 4.5*10^18, nは平方数
7+
int64_t isqrt(int64_t n)
8+
{
9+
return (int64_t)sqrt((double)n);
10+
}
11+
12+
struct result {
13+
int64_t p, q;
14+
};
15+
16+
// 入力:N <= 9*10^18
17+
struct result solve(int64_t N)
18+
{
19+
// 2080083^3 < 9*10^18 < 2080084^3
20+
for (int64_t a = 2; a <= 2080083; ++a) {
21+
if (N % a == 0) {
22+
int64_t b = N / a;
23+
if (b % a == 0) {
24+
// a = p
25+
return (struct result){.p = a, .q = b / a};
26+
} else {
27+
// a = q
28+
return (struct result){.p = isqrt(b), .q = a};
29+
}
30+
}
31+
}
32+
abort();
33+
}
34+
35+
int main()
36+
{
37+
int T;
38+
scanf("%d", &T);
39+
for (int i = 0; i < T; ++i) {
40+
int64_t N;
41+
scanf("%" SCNd64, &N);
42+
struct result r = solve(N);
43+
printf("%" PRId64 " %" PRId64 "\n", r.p, r.q);
44+
}
45+
}

‎abc/abc284-d/validate-sqrt-trunc.c‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <inttypes.h>
2+
#include <math.h>
3+
#include <stdio.h>
4+
5+
int main()
6+
{
7+
// 3037000499^2 < 2^63-1 < 3037000500^2
8+
for (int64_t i = 0; i <= 3037000499; ++i) {
9+
int64_t n = i * i;
10+
int64_t j = (int64_t)sqrt((double)n);
11+
if (i != j) {
12+
printf("%" PRId64 "\n", i);
13+
return 0;
14+
}
15+
}
16+
puts("Done");
17+
}

‎package.yaml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ dependencies:
3333
- unboxing-vector
3434
- vector-algorithms
3535
- QuickCheck
36+
- arithmoi
3637

3738
ghc-options:
3839
# Maximum heap size: 1GiB

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /