Problem:
Score : 600 points

Problem Statement

Given is an integer N.
Find the minimum possible positive integer k such that (1+2+\cdots+k) is a multiple of N.
It can be proved that such a positive integer k always exists.

Constraints

1 \leq N \leq 10^{15}

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N

Output

Print the answer in a line.

Sample Input 1

11

Sample Output 1

10

1+2+\cdots+10=55 holds and 55 is indeed a multple of N=11.
There are no positive integers k \leq 9 that satisfy the condition, so the answer is k = 10.

Sample Input 2

20200920

Sample Output 2

1100144

Solution in Rust (1.42.0) (judge verdict: Accepted)

#![allow(unused_imports, non_snake_case)]
use proconio::{
    input, fastout,
    marker::{Chars, Bytes, Usize1}
};
use std::collections::HashMap;
use std::collections::VecDeque;

pub trait ModularArithmetic: Sized {
  fn add_mod(self, other: Self, m: Self) -> Self;
  fn sub_mod(self, other: Self, m: Self) -> Self;
  fn mul_mod(self, other: Self, m: Self) -> Self;
  fn div_mod(self, other: Self, m: Self) -> Option<Self>;
  fn inv_mod(self, m: Self) -> Option<Self>;
  fn pow_mod(self, exp: Self, m: Self) -> Self;
}
impl ModularArithmetic for u64 {
  fn add_mod(self, other: u64, m: u64) -> u64 {
    let value = self + other;
    if value >= m {
      value - m
    } else {
      value
    }
  }
  fn sub_mod(self, other: u64, m: u64) -> u64 {
    if self >= other {
      self - other
    } else {
      self + m - other
    }
  }
  fn mul_mod(self, other: u64, m: u64) -> u64 {
    //(self * other) % m
    ((self as u128 * other as u128) % m as u128) as u64
  }
  fn inv_mod(self, m: u64) -> Option<u64> {
    1.div_mod(self, m)
  }
  fn div_mod(self, other: u64, m: u64) -> Option<u64> {
    let mut x = (m, 0u64);
    let mut y = (other, 1u64);
    while y.0 != 0 {
      x.1 = x.1.wrapping_sub((x.0 / y.0).wrapping_mul(y.1));
      x.0 %= y.0;
      std::mem::swap(&mut x, &mut y);
    }
    if self % x.0 != 0 {
      None
    } else {
      Some((self / x.0).mul_mod(if x.1 >= m { x.1.wrapping_add(m) } else { x.1 }, m))
    }
  }
  fn pow_mod(self, mut exp: Self, m: Self) -> Self {
    let mut x = 1;
    let mut a = self;
    while exp > 0 {
      if exp % 2 == 1 {
        x = x.mul_mod(a, m);
      }
      a = a.mul_mod(a, m);
      exp >>= 1;
    }
    x
  }
}

pub trait MillerRabin {
  fn is_prime(self) -> bool;
}
impl MillerRabin for u64 {
  fn is_prime(self: u64) -> bool {
    if self <= 3 {
      return self == 2 || self == 3;
    }
    if self % 2 == 0 {
      return false;
    }
    let r = (self - 1).trailing_zeros();
    let d = (self - 1) >> r;

    for &a in &[2, 325, 9375, 28178, 450775, 9780504, 1795265022] {
      let a = a % self;
      if a == 0 {
        continue;
      }
      let mut x = a.pow_mod(d, self);
      if x == 1 || x == self - 1 {
        continue;
      }
      let mut i = r;
      while i > 0 {
        x = x.mul_mod(x, self);
        if x == 1 {
          return false;
        } else if x == self - 1 {
          break;
        }
        i -= 1;
      }
      if i == 0 {
        return false;
      }
    }
    return true;
  }
}

pub trait IntegerSquareRootWithRemainder {
  type Output;

  /// Find ($s$, $q$) such that $n = s^2 + q$ with $n \in [s^2, (s+1)^2)$.
  fn isqrt_rem(self) -> (Self::Output, Self::Output);
}
impl IntegerSquareRootWithRemainder for u64 {
  type Output = u64;
  fn isqrt_rem(self) -> (Self::Output, Self::Output) {
    let mut one = 1 << 62;
    while one > self {
      one >>= 2;
    }
    let mut rem = self;
    let mut res = 0;
    while one > 0 {
      if rem >= res + one {
        rem -= res + one;
        res = res + 2 * one;
      }
      res >>= 1;
      one >>= 2;
    }
    (res, rem)
  }
}

pub fn binary_gcd(mut a: u64, mut b: u64) -> u64 {
  if a == 0 || b == 0 {
    return a + b;
  }
  let k = (a | b).trailing_zeros();
  a >>= a.trailing_zeros();
  b >>= b.trailing_zeros();
  while a != b {
    if a < b {
      std::mem::swap(&mut a, &mut b);
    }
    a -= b;
    a >>= a.trailing_zeros();
  }
  a << k
}

fn squfof_internal(n: u64) -> Option<u64> {
  let (sqrt_n, rem) = n.isqrt_rem();
  if rem == 0 {
    return Some(sqrt_n);
  }
  let D = if n % 4 == 1 { 2 * n } else { n };
  let (sqrt_D, mut Q) = D.isqrt_rem();
  let mut Q_hat = 1_u64;
  let mut P = sqrt_D;
  let L = (2.0 * (2.0 * (D as f64).sqrt()).sqrt()) as u64;
  let B = 2 * L;

  let mut queue = VecDeque::new();

  // println!("Step 1: {} {} {}", P, Q, L);

  let mut i = 1;
  let r = loop {
    // eprintln!("Step 2 {}: {} {}", i, P, Q);
    // 2a
    let q = (sqrt_D + P) / Q;
    let P_prime = q * Q - P;

    // 2b
    if Q <= L {
      if Q % 2 == 0 {
        queue.push_back((Q / 2, P % (Q / 2)));
      } else if 2 * Q <= L {
        queue.push_back((Q, P % Q));
      }
    }

    // 2c
    let t = Q_hat.wrapping_add(q.wrapping_mul(P.wrapping_sub(P_prime)));
    Q_hat = Q;
    Q = t;
    P = P_prime;

    // 2d
    let (r, rem) = Q.isqrt_rem();
    // maybe a typo in the paper (odd / even)
    if i % 2 == 1 && rem == 0 {
      let mut idx = 0;
      while idx < queue.len() {
        let (r_, t) = queue[idx];
        if r == r_ && P % r == t % r {
          break;
        }
        idx += 1;
      }
      if idx == queue.len() {
        break r;
      } else if r > 1 {
        queue = queue.split_off(idx + 1);
      } else {
        return None;
        //unreachable!()
      }
    }
    i += 1;

    if i >= B {
      return None;
    }
  };
  // 3
  // eprintln!("Step 3: Q_hat = {}, P = {}, r = {}", Q_hat, P, r);
  Q_hat = r;
  P = P + r * ((sqrt_D - P) / r);
  Q = (D - P * P) / Q_hat;
  assert!((D - P * P) % Q_hat == 0);

  // 4
  loop {
    // eprintln!("{} {}", P, Q);
    let q = (sqrt_D + P) / Q;
    let P_prime = q * Q - P;
    if P == P_prime {
      break;
    }
    let t = Q_hat.wrapping_add(q.wrapping_mul(P.wrapping_sub(P_prime)));
    Q_hat = Q;
    Q = t;
    P = P_prime;
  }
  // step 5
  if Q % 2 == 0 {
    return Some(Q / 2);
  } else {
    return Some(Q);
  }
}
pub fn squfof(n: u64) -> u64 {
  for m in 2.. {
    if m > 1 && n % m == 0 {
      return m;
    }
    if let Some(k) = squfof_internal(m * n) {
      let g = binary_gcd(k, n);
      if g != 1 && g != n {
        return g;
      }
    }
  }
  unreachable!();
}

pub trait Factorize: MillerRabin {
  type Output;
  fn factorize(self) -> HashMap<Self::Output, u64>;
}
impl Factorize for u64 {
  type Output = u64;
  fn factorize(self) -> HashMap<Self::Output, u64> {
    let mut result = HashMap::new();
    let mut stack = vec![self];
    while let Some(n) = stack.pop() {
      if n == 1 {
        continue;
      } else if n.is_prime() {
        *result.entry(n).or_insert(0) += 1;
      } else {
        let x = squfof(n);
        stack.push(x);
        stack.push(n / x);
      }
    }
    result
  }
}

fn extended_euclidean(u: i64, v: i64) -> i64 {
    let mut r0 = u;
    let mut r1 = v;
    let mut s0 = 1;
    let mut s1 = 0;
    let mut t0 = 0;
    let mut t1 = 1;
    while r1 != 0 {
        let q = r0 / r1;
        let r = r0 - q * r1;
        let s = s0 - q * s1;
        let t = t0 - q * t1;
        r0 = r1;
        s0 = s1;
        t0 = t1;
        r1 = r;
        s1 = s;
        t1 = t;
    }
    // println!("{} * {} + {} * {} = {}", s0, u, t0, v, r0);
    if t0 < 0 {
        t0 + u
    } else {
        t0
    }
}

#[fastout]
fn main() {
    input!{
        N: u64
    }
    let N = N * 2;
    let mut out = vec![];
    for (p, k) in N.factorize() {
        let mut v = 1;
        for _ in 0..k {
            v *= p;
        }
        out.push(v);
    }
    // println!("{:?}", out);
    let mut ans = N;
    let m = out.len();
    for bit in 0..(1 << m) {
        let mut x = 1;
        for i in 0..m {
            if (bit >> i) & 1 == 0 {
                x *= out[i];
            }
        }
        let y = N / x;
        let mut t = extended_euclidean(x as i64, y as i64) as u64;
        // println!("{} {} {}", x, y, t);
        if t * y < 2 {
            t += x;
        }
        ans = std::cmp::min(ans, y*t-1);
    }
    println!("{}", ans);
}