math/
lib.rs

1//! # Math (Core) :: Rusty
2
3/// 29m Divide Two Integers
4struct Sol29;
5
6impl Sol29 {
7    /// Divide two integers
8    ///
9    /// Examples
10    ///
11    /// ```
12    /// use rustacean::math::Sol29;
13    ///
14    /// assert_eq!(Sol29::divide(10, 3), 3);
15    /// ```
16    ///
17    pub fn divide(dividend: i32, divisor: i32) -> i32 {
18        if dividend == divisor {
19            return 1;
20        }
21
22        let psign = (dividend < 0) == (divisor < 0);
23        let (mut n, d) = (dividend.unsigned_abs(), divisor.unsigned_abs());
24
25        let mut r: u32 = 0;
26        while n >= d {
27            let mut p = 0;
28            while n > (d << (p + 1)) {
29                p += 1;
30            }
31
32            r += 1 << p;
33            n -= d << p;
34        }
35
36        if r == 1 << 31 && psign {
37            return i32::MAX; // (1<<31) -1
38        }
39
40        match psign {
41            true => r as i32,
42            _ => -(r as i32),
43        }
44    }
45}
46
47/// 335h Self Crossing
48struct Sol335 {}
49
50impl Sol335 {
51    pub fn is_self_crossing(distance: Vec<i32>) -> bool {
52        if distance.windows(4).any(|w| w[0] >= w[2] && w[3] >= w[1]) {
53            return true;
54        }
55
56        if distance
57            .windows(5)
58            .any(|w| w[1] == w[3] && w[0] + w[4] >= w[2])
59        {
60            return true;
61        }
62
63        if distance
64            .windows(6)
65            .any(|w| w[3] >= w[1] && w[2] > w[4] && w[0] + w[4] >= w[2] && w[1] + w[5] >= w[3])
66        {
67            return true;
68        }
69
70        false
71    }
72}
73
74/// 587h Erect the Fence
75struct Sol587 {}
76
77impl Sol587 {
78    /// 1 <= N <= 3000
79    /// 0 <= x_i, y_i <= 100
80    pub fn outer_trees(mut trees: Vec<[i32; 2]>) -> Vec<[i32; 2]> {
81        if trees.len() <= 3 {
82            return trees;
83        }
84
85        trees.sort_unstable();
86
87        // Cross-Product
88        // OA-> X OB->
89        fn cross_prd(o: &[i32; 2], a: &[i32; 2], b: &[i32; 2]) -> i32 {
90            (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])
91        }
92
93        let mut lower = vec![];
94        for p in trees.iter() {
95            while lower.len() >= 2
96                && cross_prd(lower[lower.len() - 2], lower[lower.len() - 1], p) < 0
97            {
98                lower.pop();
99            }
100            lower.push(p);
101        }
102
103        let mut upper = vec![];
104        for p in trees.iter().rev() {
105            while upper.len() >= 2
106                && cross_prd(upper[upper.len() - 2], upper[upper.len() - 1], p) < 0
107            {
108                upper.pop();
109            }
110            upper.push(p);
111        }
112
113        let mut convex_hull: Vec<_> = lower[..lower.len() - 1]
114            .into_iter()
115            .chain(upper[..upper.len() - 1].into_iter())
116            .map(|&&p| p)
117            .collect();
118
119        convex_hull.sort();
120        convex_hull.dedup();
121        convex_hull
122    }
123}
124
125/// 838m Push Dominoes
126struct Sol838;
127
128impl Sol838 {
129    pub fn push_dominoes(dominoes: String) -> String {
130        let n = dominoes.len();
131        let mut force = vec![0; n];
132
133        let mut r = 0;
134        for (i, chr) in dominoes.chars().enumerate() {
135            r = match chr {
136                'R' => n as i32,
137                'L' => 0,
138                _ => (r - 1).max(0),
139            };
140
141            force[i] += r;
142        }
143
144        let mut l = 0;
145        for (i, chr) in dominoes.chars().rev().enumerate() {
146            l = match chr {
147                'R' => 0,
148                'L' => n as i32,
149                _ => (l - 1).max(0),
150            };
151
152            force[n - 1 - i] -= l;
153        }
154
155        println!("-> {:?}", force);
156
157        force
158            .iter()
159            .map(|&f| match f {
160                ..=-1 => 'L',
161                1.. => 'R',
162                _ => '.',
163            })
164            .collect()
165    }
166}
167
168/// 908 Smallest Range I
169struct Sol908;
170
171impl Sol908 {
172    pub fn smallest_range_i(nums: Vec<i32>, k: i32) -> i32 {
173        let mx = nums.iter().max();
174        let mn = nums.iter().min();
175
176        println!(" -> {:?} {:?}", mx, mn);
177
178        match (nums.iter().max(), nums.iter().min()) {
179            (Some(x), Some(n)) => 0.max(x - n - 2 * k),
180            _ => 0,
181        }
182    }
183}
184
185/// 970m Powerful Integers
186struct Sol970;
187
188impl Sol970 {
189    /// 1 <= x,y <= 100
190    /// 0 <= bound <= 10^6
191    pub fn powerful_integers(x: i32, y: i32, bound: i32) -> Vec<i32> {
192        use std::collections::HashSet;
193
194        let mut p_x = vec![1];
195        let mut p_y = vec![1];
196
197        if x > 1 {
198            let mut p = x;
199            while p < bound {
200                p_x.push(p);
201                p *= x;
202            }
203        }
204        if y > 1 {
205            let mut p = y;
206            while p < bound {
207                p_y.push(p);
208                p *= y;
209            }
210        }
211
212        let mut set = HashSet::new();
213        for x in &p_x {
214            for y in &p_y {
215                if x + y <= bound {
216                    set.insert(x + y);
217                }
218            }
219        }
220
221        set.drain().collect()
222    }
223}
224
225/// 989 Add to Array-Form of Integer
226struct Sol989;
227
228impl Sol989 {
229    pub fn add_to_array_form(num: Vec<i32>, k: i32) -> Vec<i32> {
230        println!(
231            " -> {:?}",
232            std::iter::successors(Some((k, 0, num.len())), |(mut carry, _, mut p)| {
233                match carry > 0 || p > 0 {
234                    true => {
235                        if p > 0 {
236                            p -= 1;
237                            carry += num[p];
238                        }
239                        Some((carry / 10, carry % 10, p))
240                    }
241                    _ => None,
242                }
243            })
244            .map(|(_, d, _)| d)
245            .skip(1)
246            .fold(vec![], |mut rst, d| {
247                rst.push(d);
248                rst
249            })
250        );
251
252        let mut rst = vec![];
253
254        let (mut carry, mut p) = (k, num.len());
255        while carry > 0 || p > 0 {
256            if p > 0 {
257                p -= 1;
258                carry += num[p]
259            }
260            rst.push(carry % 10);
261            carry /= 10;
262        }
263
264        println!(" -> {rst:?}");
265
266        rst.reverse();
267        rst
268    }
269}
270
271/// 1295 Find Numbers with Even Number of Digits
272struct Sol1295;
273
274impl Sol1295 {
275    pub fn find_numbers(nums: Vec<i32>) -> i32 {
276        println!(
277            ":: {}",
278            nums.iter()
279                .filter(|&&n| {
280                    let mut digits = 0;
281                    let mut n = n;
282                    while n > 0 {
283                        n /= 10;
284                        digits += 1;
285                    }
286
287                    digits & 1 == 0
288                })
289                .count()
290        );
291
292        nums.iter()
293            .map(|&n| {
294                let mut digits = 0;
295                let mut n = n;
296                while n > 0 {
297                    n /= 10;
298                    digits += 1;
299                }
300
301                (digits + 1) & 1
302            })
303            .sum()
304    }
305}
306
307/// 1432m Max Difference You Can Get From Changing an Integer
308struct Sol1432 {}
309
310impl Sol1432 {
311    pub fn max_diff(num: i32) -> i32 {
312        let darr: Vec<_> = num
313            .to_string()
314            .as_bytes()
315            .iter()
316            .map(|&chr| (chr - b'0') as i32)
317            .collect();
318
319        let mut vmin = num;
320        match darr[0] {
321            1 => {
322                if let Some(&m) = darr[1..].iter().find(|&&d| d != 1 && d != 0) {
323                    vmin = 1;
324                    for &d in &darr[1..] {
325                        vmin = 10 * vmin + if d == m { 0 } else { d };
326                    }
327                }
328            }
329            _ => {
330                vmin = 0;
331                for &d in &darr {
332                    vmin = 10 * vmin + if d == darr[0] { 1 } else { d };
333                }
334            }
335        }
336
337        let mut vmax = num;
338        if let Some(&x) = darr.iter().find(|&d| d != &9) {
339            vmax = 0;
340            for &d in &darr {
341                vmax = 10 * vmax + if d == x { 9 } else { d };
342            }
343        }
344
345        println!("-> {vmin} {vmax}");
346
347        vmax - vmin
348    }
349}
350
351/// 1780m Check if Number is a Sum of Powers of Three
352struct Sol1780;
353
354impl Sol1780 {
355    /// 1 <= N <= 10^7
356    pub fn check_powers_of_three(n: i32) -> bool {
357        use std::iter::successors;
358
359        let mut powers: Vec<_> = successors(Some(1), |p| {
360            if 3 * p <= 1e7 as i32 {
361                Some(3 * p)
362            } else {
363                None
364            }
365        })
366        .collect();
367        powers.reverse();
368
369        println!("-> {:?}", powers);
370
371        let mut n = n;
372        for p in powers {
373            if n >= p {
374                n -= p;
375                if n == 0 {
376                    return true;
377                }
378            }
379        }
380
381        false
382    }
383
384    /// O(2^log3(N))
385    fn check_powers_of_three_recursive(n: i32) -> bool {
386        fn search(n: i32, power: i32) -> bool {
387            if n == 0 {
388                return true;
389            }
390            if n < power {
391                return false;
392            }
393
394            search(n, 3 * power) || search(n - power, 3 * power)
395        }
396
397        search(n, 1)
398    }
399}
400
401/// 2081h Count of k-Mirror Numbers
402struct Sol2081 {}
403
404impl Sol2081 {
405    /// 2 <= k <= 9
406    /// 1 <= n <= 30
407    pub fn k_mirror(k: i32, mut n: i32) -> i64 {
408        let k = k as i64;
409
410        let k_palindrome = |mut p| {
411            let mut digits = vec![];
412            while p > 0 {
413                digits.push(p % k);
414                p /= k;
415            }
416
417            let (mut l, mut r) = (0, digits.len() - 1);
418            while l < r {
419                if digits[l] != digits[r] {
420                    return false;
421                }
422                l += 1;
423                r -= 1;
424            }
425
426            println!("-> + {digits:?}");
427            true
428        };
429
430        let mut total = 0;
431
432        let mut start = 1;
433        loop {
434            for mut p in start..start * 10 {
435                let mut t = p / 10;
436                while t > 0 {
437                    p *= 10;
438                    p += t % 10;
439                    t /= 10;
440                }
441                println!("-> (O) {p}");
442
443                if k_palindrome(p) {
444                    total += p;
445                    n -= 1;
446                    if n == 0 {
447                        return total;
448                    }
449                }
450            }
451
452            for mut p in start..start * 10 {
453                let mut t = p;
454                while t > 0 {
455                    p *= 10;
456                    p += t % 10;
457                    t /= 10;
458                }
459                println!("-> (E) {p}");
460
461                if k_palindrome(p) {
462                    total += p;
463                    n -= 1;
464                    if n == 0 {
465                        return total;
466                    }
467                }
468            }
469
470            start *= 10;
471        }
472    }
473}
474
475/// 2338h Count the Number of Ideal Arrays
476struct Sol2338;
477
478impl Sol2338 {
479    /// 2 <= N <= 10^4, 1 <= Max <= 10^4
480    /// Choose & Multi-Choose :: C((n/k)) = C(n+k-1/k)
481    pub fn ideal_arrays(n: i32, max_value: i32) -> i32 {
482        const P: usize = 15;
483
484        let mut sieve: Vec<usize> = (0..=max_value as usize).collect();
485        for p in 2..sieve.len() {
486            if sieve[p] == p {
487                for m in (p * p..sieve.len()).step_by(p) {
488                    sieve[m] = p;
489                }
490            }
491        }
492        println!("-> Sieve :: {sieve:?}");
493
494        let mut factors = vec![vec![]; max_value as usize + 1];
495        for (n, _) in sieve
496            .iter()
497            .enumerate()
498            .take(max_value as usize + 1)
499            .skip(2)
500        {
501            let mut x = n;
502            while x > 1 {
503                let factor = sieve[x];
504                let mut count = 0;
505                while x % factor == 0 {
506                    x /= factor;
507                    count += 1;
508                }
509                factors[n].push(count);
510            }
511        }
512        println!("-> Factors Counts: {factors:?}");
513
514        let mut c = vec![vec![0; P + 1]; n as usize + P + 1];
515        c[0][0] = 1;
516
517        const M: i64 = 1_000_000_007;
518        for n in 1..c.len() {
519            c[n][0] = 1;
520            for k in 1..=n.min(P) {
521                c[n][k] = (c[n - 1][k] + c[n - 1][k - 1]) % M
522            }
523        }
524
525        (1..=max_value as usize).fold(0, |count, v| {
526            let mut total = 1;
527            for &k in &factors[v] {
528                total = total * c[n as usize + k - 1][k] % M;
529            }
530
531            (count + total) % M
532        }) as i32
533    }
534}
535
536/// 2523m Closest Prime Numbers in Range
537struct Sol2523;
538
539impl Sol2523 {
540    pub fn closest_primes(left: i32, right: i32) -> Vec<i32> {
541        let mut sieve = vec![0; 1 + right as usize];
542
543        for (i, n) in sieve
544            .iter_mut()
545            .enumerate()
546            .take(right as usize + 1)
547            .skip(2)
548        {
549            *n = i;
550        }
551
552        for p in 2..=right as usize {
553            if sieve[p] == p {
554                for m in (p * p..=right as usize).step_by(p) {
555                    sieve[m] = p;
556                }
557            }
558        }
559
560        println!("-> {:?}", sieve);
561
562        let primes: Vec<_> = sieve
563            .into_iter()
564            .enumerate()
565            .skip(1)
566            .filter(|(i, p)| i == p && *p as i32 >= left)
567            .map(|(_, p)| p as i32)
568            .collect();
569
570        println!("-> {:?}", primes);
571
572        primes.windows(2).fold(vec![-1, -1], |rst, v| {
573            if rst == vec![-1, -1] || v[1] - v[0] < rst[1] - rst[0] {
574                vec![v[0], v[1]]
575            } else {
576                rst
577            }
578        })
579    }
580}
581
582/// 2566 Maximum Difference by Remapping a Digit
583struct Sol2566 {}
584
585impl Sol2566 {
586    /// 1 <= N <= 10^8
587    pub fn min_max_difference(num: i32) -> i32 {
588        let nstr: Vec<_> = num.to_string().chars().collect();
589
590        if let Some(p) = num.to_string().chars().position(|chr| chr != '9') {
591            let vmax = nstr
592                .iter()
593                .map(|&chr| {
594                    if chr == nstr[p] {
595                        9
596                    } else {
597                        chr.to_digit(10).unwrap_or(0)
598                    }
599                })
600                .fold(0, |r, d| r * 10 + d);
601
602            let vmin = nstr
603                .iter()
604                .map(|&chr| {
605                    if chr == nstr[0] {
606                        0
607                    } else {
608                        chr.to_digit(10).unwrap_or_default()
609                    }
610                })
611                .fold(0, |r, d| r * 10 + d);
612
613            println!("-> {vmin} ~ {vmax}");
614
615            return (vmax - vmin) as i32;
616        }
617
618        num
619    }
620}
621
622/// 2579m Count Total Number of Colored Cells
623struct Sol2578;
624
625impl Sol2578 {
626    pub fn colored_cells(n: i32) -> i64 {
627        let mut rst = 1;
628        for n in 2..=n as i64 {
629            rst += 4 * (n - 1);
630        }
631
632        rst
633    }
634}
635
636/// 2818h Apply Operations to Maximize Score
637struct Sol2818;
638
639impl Sol2818 {
640    /// 1 <= N, N_i <= 10^5
641    pub fn maximum_score(nums: Vec<i32>, k: i32) -> i32 {
642        let mut omega = vec![0; 1 + 1e5 as usize];
643        for p in 2..omega.len() {
644            if omega[p] == 0 {
645                for m in (p..omega.len()).step_by(p) {
646                    omega[m] += 1;
647                }
648            }
649        }
650
651        const M: i64 = 7 + 1e9 as i64;
652        fn mpower(mut b: i64, mut e: i64) -> i64 {
653            let mut r = 1;
654            while e > 0 {
655                if e & 1 == 1 {
656                    r = (r * b) % M;
657                }
658                b = (b * b) % M;
659                e >>= 1;
660            }
661
662            r
663        }
664
665        let n = nums.len();
666        let (mut left, mut right) = (vec![-1; n], vec![n as i32; n]);
667
668        let mut stack: Vec<usize> = vec![];
669
670        for (i, &v) in nums.iter().enumerate() {
671            while !stack.is_empty()
672                && omega[nums[stack[stack.len() - 1]] as usize] < omega[v as usize]
673            {
674                right[stack.pop().unwrap()] = i as i32;
675            }
676
677            if !stack.is_empty() {
678                left[i] = *stack.last().unwrap() as i32;
679            }
680
681            stack.push(i);
682        }
683
684        let mut set = vec![];
685        for e in nums
686            .iter()
687            .map(|&v| v as i64)
688            .zip((0..n as i32).zip(left.iter().zip(right.iter())))
689        {
690            set.push(e);
691        }
692        set.sort_by_key(|e| -e.0);
693
694        println!("-> {:?}", set);
695
696        let mut score = 1i64;
697        let mut k = k;
698        for (v, (i, (l, r))) in set {
699            let total = (i - l) as i64 * (r - i) as i64;
700            if total >= k as i64 {
701                score = score * mpower(v, k as i64) % M;
702                break;
703            }
704            score = score * mpower(v, total) % M;
705            k -= total as i32;
706        }
707
708        score as i32
709    }
710}
711
712/// 2843 Count Symmetric Integers
713struct Sol2843;
714
715impl Sol2843 {
716    pub fn count_symmetric_integers(low: i32, high: i32) -> i32 {
717        let mut count = 0;
718
719        for n in low..=high {
720            let n = n.to_string();
721            let n = n.as_bytes();
722            let w = n.len();
723            if w & 1 == 0 {
724                let (mut left, mut right) = (0, 0);
725                for i in 0..w / 2 {
726                    left += n[i];
727                    right += n[w / 2 + i];
728                }
729                if left == right {
730                    count += 1;
731                }
732            }
733        }
734
735        // 1 <= N_i <= 10^4
736        println!(
737            "-> {}",
738            (low..=high).fold(0, |r, n| {
739                match n {
740                    1..100 if n % 11 == 0 => r + 1,
741                    1000..10000 => {
742                        if n / 1000 + (n % 1000) / 100 == (n % 100) / 10 + (n % 10) {
743                            r + 1
744                        } else {
745                            r
746                        }
747                    }
748                    _ => r,
749                }
750            })
751        );
752
753        count
754    }
755}
756
757/// 2929m Distribute Candies Among Children II
758struct Sol2929 {}
759
760impl Sol2929 {
761    /// 1 <= N, L <= 10^6
762    pub fn distribute_candies(n: i32, limit: i32) -> i64 {
763        let mut ways = 0;
764        for candy1 in 0..=limit.min(n) {
765            if n - candy1 <= 2 * limit {
766                println!(
767                    "-> Candy1: {candy1} | Candy2: {} ~ {}",
768                    (n - candy1).min(limit),
769                    0.max(n - candy1 - limit)
770                );
771
772                ways += ((n - candy1).min(limit) - (n - candy1 - limit).max(0) + 1) as i64
773            }
774        }
775
776        ways
777    }
778}
779
780/// 3024 Type of Triangle
781struct Sol3024;
782
783impl Sol3024 {
784    pub fn triangle_type(nums: Vec<i32>) -> String {
785        let mut nums = nums;
786        nums.sort();
787
788        let (a, b, c) = (nums[0], nums[1], nums[2]);
789        if a + b <= c {
790            "none"
791        } else if a == c {
792            "equilateral"
793        } else if a == b || b == c {
794            "isosceles"
795        } else {
796            "scalene"
797        }
798        .to_string()
799    }
800}
801
802/// 3272h Find the Count of Good Integers
803struct Sol3272;
804
805impl Sol3272 {
806    /// 1 <= n <= 10, 1 <= k <= 9
807    pub fn count_good_integers(n: i32, k: i32) -> i64 {
808        use std::collections::HashSet;
809
810        let mut set: HashSet<String> = HashSet::new();
811
812        let start = 10u32.pow((n - 1) as u32 / 2);
813        for v in start..10 * start {
814            let left = v.to_string();
815            let right: String = left.chars().rev().skip((n & 1) as usize).collect();
816
817            let palindrome = format!("{}{}", left, right);
818            match palindrome.parse::<u64>() {
819                Ok(v) if v % k as u64 == 0 => {
820                    let mut chrs: Vec<char> = palindrome.chars().collect();
821                    chrs.sort_unstable();
822                    set.insert(chrs.iter().collect());
823                }
824                _ => {}
825            }
826        }
827
828        println!("-> {:?}", set);
829
830        let mut facts = vec![1; (n + 1) as usize];
831        for n in 2..=n as usize {
832            facts[n] = facts[n - 1] * n;
833        }
834
835        let mut count = 0;
836        for chrs in set {
837            let mut counter = [0; 10];
838            for chr in chrs.as_bytes() {
839                counter[(chr - b'0') as usize] += 1;
840            }
841
842            let mut perms = (n as usize - counter[0]) * facts[n as usize - 1];
843            for &count in counter.iter() {
844                perms /= facts[count];
845            }
846
847            count += perms;
848        }
849
850        count as i64
851    }
852}
853
854/// 3405h Count the Number of Arrays with K Matching Adjacent Elements
855struct Sol3405 {}
856
857impl Sol3405 {
858    pub fn count_good_arrays(n: i32, m: i32, k: i32) -> i32 {
859        const M: i64 = 1e9 as i64 + 7;
860
861        let mut facts = vec![0; n as usize];
862        let mut ifacts = vec![0; n as usize];
863
864        let power = |mut b, mut e| {
865            let mut power = 1;
866            while e > 0 {
867                if e & 1 == 1 {
868                    power = power * b % M;
869                }
870                b = b * b % M;
871                e >>= 1;
872            }
873
874            power
875        };
876
877        facts[0] = 1;
878        for i in 1..facts.len() {
879            facts[i] = facts[i - 1] * i as i64 % M;
880        }
881
882        ifacts[n as usize - 1] = power(facts[n as usize - 1], M - 2);
883        for i in (1..ifacts.len()).rev() {
884            ifacts[i - 1] = ifacts[i] * i as i64 % M;
885        }
886
887        let n_choose_k = |n, k| facts[n] * ifacts[k] % M * ifacts[n - k] % M;
888
889        (m as i64 * n_choose_k(n as usize - 1, k as usize) % M
890            * power(m as i64 - 1, (n - k - 1) as i64)
891            % M) as _
892    }
893}
894
895/// 3443m Maximum Manhattan Distance After K Changes
896struct Sol3443 {}
897
898impl Sol3443 {
899    pub fn max_distance(s: String, k: i32) -> i32 {
900        let (mut lat, mut long) = (0i32, 0i32);
901        s.chars().enumerate().fold(0, |xdist, (i, dir)| {
902            match dir {
903                'N' => lat += 1,
904                'S' => lat -= 1,
905                'W' => long += 1,
906                'E' => long -= 1,
907                _ => (),
908            }
909
910            xdist.max((i as i32 + 1).min(lat.abs() + long.abs() + 2 * k))
911        })
912    }
913}
914
915#[cfg(test)]
916mod tests;