Study Notes
Foundationscore

Modular Arithmetic for DSA

The habits that keep big numbers inside a long — reduce as you go, fixing negative remainders — plus the clean-thinking tricks (parity, jump to the next multiple, div & mod as a pair, circular indexing) and, when a problem asks for it, binary exponentiation and the modular inverse.

35 min read·verified Java 21·reviewed 2026-08-30

Assumes you know

After this you should be able to

  • Keep modular calculations overflow-safe
  • Use fast exponentiation and modular inverses
overflow-safediv & mod tricksMod Inverse

DSA Study Reference · Java

Five habits that keep giant numbers inside a long the whole way through — why problems ask for mod 109+7, reducing as you go, binary exponentiation, modular inverse via Fermat, and the overflow-safe tricks that keep your thinking clean.

Java Overflow-safe patterns Light + dark ready
Section 1

Quick Reference#

The whole page on one screen. Everything here is unpacked in full below. Watch for the marked lines: ★ trick · ⚠ pitfall · 💡 tip.

CORE IDEA
  • a % m = remainder after dividing a by m  → range 0 .. m-1
  • "answer mod M" asked → true answer is huge, they want the remainder
  • Real enemy = overflow, not the big final number
TYPES
  • int = 32-bit, max ~2.1e9
  • long = 64-bit, max ~9.2e18
  • ⚠values that can grow → type them long from the start
  • literal: 1_000_000_007L (note the L)
WHY 109+7 (M)
  • 1) prime → lets you divide (inverse exists), unique remainders
  • 2) sweet spot: M+M < int, M*M < long
  • 💡also 998244353 (for FFT/NTT) & 10^9+9
THE 5 RULES
  • R1 use long everywhere; mod = 1_000_000_007L
  • R2 take TWO at a time: ((a*b)%M * (c%M))%M
  • ⚠a*b*c overflows before % ever runs
  • R3 never Math.pow() (double!) → binary expo
  • R4 don't divide → multiply by inverse
  • R5 print: ((ans % M) + M) % M kills negatives
  • 💡Java shortcut: Math.floorMod(a, M)
PROPERTIES (mod pushes inside +,-,*)
  • (a+b)%M = (a%M + b%M)%M
  • (a-b)%M = (a%M - b%M + M)%M
  • (a*b)%M = (a%M * b%M)%M
  • ⚠DIVISION does NOT distribute → inverse
BINARY EXPO (a^b % M, O(log b))
  • b even → square: (a^(b/2))^2
  • b odd  → peel one: a * a^(b-1)
  • base b=0 → return 1
  • doodle: b in binary, each bit doubles the base; set bits get multiplied in
INVERSE (Fermat, M prime)
  • FLT: a^(M-1) % M = 1 → a * a^(M-2) = 1
  • ★inv(a) = binpow(a, M-2)  ← a^-1
  • (a/b)%M = a * inv(b) % M
  • use for nCr, probabilities, avg, any "/" under mod
  • ⚠needs M prime; else Extended Euclid
n(n+1)/2 & MULTIPLES
  • sum 1..n = n(n+1)/2; halve the EVEN one first
  • steps to next multiple of k: (k - x%k) % k
  • ceil divide (no floats): (x + k - 1) / k
  • ⚠never Math.ceil((double)x/k) for big longs
Section 2

Detailed Walkthrough#

The trap. Your logic is right and the small cases pass, but on a big case the answer comes out negative — garbage where you expected trillions. Nothing in the logic is wrong. The true answer had hundreds of digits, a long holds ~19, and it silently wrapped around. That's why the problem says "print the answer modulo 109+7": it hands you the one tool that keeps every intermediate value inside the box. The five habits below are the whole survival kit — each is just a way to reduce early and never let a value grow too large.

💡 What to actually internalize Day to day you mostly need three reflexes: keep growing values in a long, reduce with % after every step, and the /-and-% reading tricks (parity, next multiple, circular index). Binary exponentiation and the modular inverse only appear when a problem explicitly asks for "answer mod a prime" — build the reflexes first, and reach for those two when a problem demands them.

1. What "mod" actually is, and why problems ask for it#

The modulo of a number is simply the remainder left over after division. 17 % 5 = 2, because 17 = 3×5 + 2.

The clock analogy. A 12-hour clock is arithmetic mod 12. It's 10 o'clock, you add 5 hours — not 15 o'clock, it's 3. The clock silently did 15 % 12 = 3. Every value on the face lives in 0..11 no matter how much time you add. Modular arithmetic is exactly this: a number line rolled into a circle of size m, where everything stays inside 0 .. m-1.

012 345.. infinite line → wraps every m steps "roll it into a circle" 012 3..m-2 m-1
Every integer collapses onto one of m positions on the circle. That's all mod does.

When a problem ends with "return the answer modulo 109+7," it's telling you the true count is astronomically large — think number of ways to arrange things, which explodes factorially. Nobody can store or check a 100-digit number, so everyone compares just the remainder mod a fixed prime. If your remainder matches theirs, your logic was right.

2. int vs long, and the L suffix#

Overflow is the whole game, so the first move is knowing exactly how much room each type gives you and typing the wide one on purpose. Anything that could grow past a couple billion goes in a long from the start — not an int you widen later.

TypeHolds up toNamed limit
int (32-bit)~2.1 × 109 (231−1)Integer.MAX_VALUE = 2147483647
long (64-bit)~9.2 × 1018 (263−1)Long.MAX_VALUE = 9223372036854775807
Java note — the L suffix An integer literal without a suffix is an int. Writing long mod = 1000000007; is fine (it fits), but 1000000007 * 1000000007 computes as int × int first, overflows, then widens — giving garbage. Always suffix modulus and big literals with L: long MOD = 1_000_000_007L;. The underscores are just readability (Java allows them in numeric literals).

3. Why that exact number, and the "sweet spot"#

109+7 is often called a "sweet spot." Two properties earn it that name.

PropertyWhat it buys you
It's primeEvery non-zero value has a modular inverse (Fermat needs a prime), so you can divide. Remainders are also "spread out" — fewer accidental collisions.
Sweet spot for sizeAny value stays < 109+7. Add two → ~2×109 (still near int range). Multiply two → ~1018, which fits comfortably in a long (max 9.2×1018). So (a%M)*(b%M) never overflows a long.
💡 Tip You'll also meet 109+9 (a twin prime, handy for double hashing) and 998244353 (a prime of the form c·223+1, the standard modulus for NTT/FFT problems). If a problem hands you a non-prime modulus — as in the GP sum below — Fermat's inverse breaks and you need a different method.
The Five Rules

When you hit a modulo problem, run these#

Rule 1Use long everywhere#

The first defense is to never touch a 32-bit int for values that could grow. Declare the modulus and every running value as long from the start, so nothing has a chance to overflow before you reduce it.

long MOD = 1_000_000_007L;   // modulus as a long constant
long ans = 0, prod = 1;    // running values are long, not int
Java note Beware method signatures: if you read input as int and multiply, the multiply happens in int space before assignment to a long. Read big inputs into long, or cast the first operand: (long) a * b. Reading via Long.parseLong(...) or new Scanner(System.in).nextLong() keeps you safe.

Rule 2Take two at a time#

Never combine three or more factors before reducing. Multiply two, take % M, then bring in the next one.

Here's the danger: in (a * b * c) % M, the product a * b may already have overflowed before the * c or the % M ever runs. The modulo can't rescue a value that's already garbage. So fold in one factor at a time, reducing after each step.

⚠ a * b * c then % M a × b × c a×b already overflowed the long ★ two at a time (a*b)%M (t * c%M)%M every partial stays < M
Fold one factor in at a time. Each intermediate product stays below M×M, safely inside a long.
(a × b × c) % M  =  ( ((a × b) % M) × (c % M) ) % M
// Rule 2 in Java: fold in one factor at a time
long temp = (a % MOD) * (b % MOD) % MOD;   // two at a time
temp = temp * (c % MOD) % MOD;             // then the third

The properties this rests on#

Mod distributes over +, −, and × — reducing early only discards whole multiples of M, which never affect a remainder. That's why "two at a time" is legal.

(a + b) % M = (a%M + b%M) % M
(a − b) % M = (a%M − b%M + M) % M
(a × b) % M = (a%M × b%M) % M
(a ÷ b) % M ≠ (a%M) ÷ (b%M)  ← division is special (Rule 4)

Rule 3Never use Math.pow() — binary exponentiation#

Math.pow() returns a double, which can't hold a large integer exactly and gives you no way to reduce mod M partway through. So (long) Math.pow(a, b) % MOD silently returns wrong answers for large exponents — rounding error, plus the value overflows before the modulo ever runs. The fix is to write the power yourself.

⚠ Pitfall Math.pow(10, 18) is a double and can't represent that integer exactly. And you can't reduce mod M during a Math.pow call, so the intermediate value overflows anyway. For modular powers, always write your own integer routine.

The naive fix is a loop — multiply a into the answer b times, reducing each step. That's O(b), too slow when b is up to 109.

// O(b) - correct but too slow for large b
long ans = 1;
for (int i = 0; i < b; i++) ans = ans * a % MOD;

Binary exponentiation computes ab % M in O(log b) by squaring the base and halving the exponent — because ab = (ab/2)2 when b is even, and you peel off one factor when b is odd.

a1 a2 a4 a8 squaresquaresquare 1 0 1 1 13 = 1101₂ → multiply in a¹, a⁴, a⁸ (the set bits)
Square across the top; multiply into the answer only where the exponent bit is 1. ~30 steps instead of a billion.

Recursive version#

The recursive form reads exactly like the math: base case b == 0 returns 1, an odd b peels off one factor, an even b squares the half.

static long MOD = 1_000_000_007L;

static long binpow(long a, long b) {
    if (b == 0) return 1;              // base case
    if ((b & 1) == 1)                    // b is odd
    return a % MOD * binpow(a, b - 1) % MOD;
    long temp = binpow(a, b / 2);        // b is even
    return temp * temp % MOD;
}

Iterative version (preferred in Java — no stack risk)#

Java note — why iterate The recursive form is clean, but with b up to 109 the odd-branch adds a call per bit and Java's default stack is shallower than you might expect. The iterative form is the same O(log b) with zero recursion — the version to memorize for contests.
static long power(long a, long b) {
    a %= MOD;
    long res = 1;
    while (b > 0) {
        if ((b & 1) == 1) res = res * a % MOD;  // bit set → multiply in
        a = a * a % MOD;                        // square the base
        b >>= 1;                                 // next bit
    }
    return res;
}
💡 Tip — the built-in escape hatch Java ships BigInteger.modPow(exp, mod), which does exactly this without overflow worries: BigInteger.valueOf(a).modPow(BigInteger.valueOf(b), BigInteger.valueOf(MOD)).longValue(). It's slower (object overhead) but bulletproof — good for a quick correct baseline or when you're unsure about overflow. In hot loops, prefer your own long routine.

Rule 4In modulo you don't divide — you take the inverse #

Plain division breaks under a modulus: (12 / 6) % 10 = 2, but reducing first gives (12%10) / (6%10) = 2/6, which isn't even an integer. Remainders throw away the information division needs.

To divide by b under a modulus, multiply by b's modular inverse — the number that plays the role of 1/b, i.e. the x with (b · x) % M = 1.

A concrete example: find x so that (6 · x) % 7 = 1. Testing, 6 · 6 = 36, and 36 % 7 = 1 — so 6-1 = 6 under mod 7. Dividing by 6 becomes multiplying by 6. But guessing doesn't scale, which is where Fermat comes in.

(a / b) % M  =  a × b-1 % M

Fermat's Little Theorem:   a(M−1) % M = 1  (M prime, gcd(a,M)=1)

⇒   a × a(M−2) % M = 1   ⇒   b-1 = b(M−2) % M

The key formula is exactly this last step: the inverse of any a is aM-2, which you already know how to compute fast with binary exponentiation. So inv is a one-liner on top of power.

// modular inverse via Fermat (MOD must be prime)
static long inv(long x) {
    return power(x, MOD - 2);      // x^(M-2) % M  ==  x^-1
}
// then:  (a / b) % M   becomes   a * inv(b) % MOD
⚠ Pitfall Fermat's inverse requires M prime and gcd(b, M) = 1 (so b is not a multiple of M, and never 0). If the modulus is composite — the GP problem's Case 2 — use the Extended Euclidean algorithm instead, which finds the inverse whenever gcd(b, M) = 1. There's no 1/0 in any world, so a zero denominator has no inverse.
💡 Tip — where you'll actually use inverse Any answer that's a ratio: binomial coefficients nCr = n! / (r!(n-r)!), probabilities and expected values, averages, or a problem that literally asks for P · Q-1 mod M (that's Worked Problem 1). Precompute factorials and their inverses once and every nCr is an O(1) lookup.

Rule 5Fix negatives when printing#

The % operator can return a negative result when the left side is negative: -3 % 7 gives -3, not the mathematically clean 4. A negative remainder fails comparisons and corrupts later steps — and it's how a "correct" solution ends up printing a negative final answer.

⚠ Pitfall After any subtraction under a modulus (like (b - c) % M where c > b), the result can be negative. Always add M then take % M again: ((ans % M) + M) % M. The + M lifts it back positive; the final % M trims it if it was already fine.
// Rule 5 - the guaranteed-positive print
System.out.println(((ans % MOD) + MOD) % MOD);
Java note — the one-liner shortcut Java has a built-in that does exactly this: Math.floorMod(a, m) always returns a result with the sign of m — so for positive M it's always in [0, M). Math.floorMod(-3, 7) returns 4. You can use it as a drop-in for the ((a % M) + M) % M dance. (There's also Math.floorDiv for matching floored division.) Both are worth knowing: the manual form works anywhere, and floorMod is the clean one-liner when you reach for it.
Clean-thinking tricks

Small moves that keep the logic clean#

The n(n+1)/2 trap#

The sum 1 + 2 + ... + n = n(n+1)/2. The final answer fits fine, but the intermediate product n * (n+1) can overflow before you divide by 2. For n ≈ 3×109, n(n+1) already blows past a long.

★ Trick — halve the even one first Among any two consecutive integers n and n+1, exactly one is even. Divide the even one by 2 before multiplying — same result, but the peak intermediate value is halved (a full extra bit of headroom), and the division stays exact.
static long tri(long n) {
    return (n % 2 == 0) ? (n / 2) * (n + 1) : n * ((n + 1) / 2);
}
⚠ Pitfall — can't do this in mod space If the problem wants n(n+1)/2 % M and n is up to 1018, reduce n and n+1 mod M first — but then you've lost which was even, and /2 is no longer plain division. Multiply by inv(2) instead: n%M * ((n+1)%M) %M * inv(2) %M.

Reaching the next multiple of k#

x % k is how far past the last multiple of k you are, so k - (x % k) is the gap to the next one. If x is already a multiple that gives k (wrong — should be 0), so one outer % k fixes the edge case.

steps to next multiple of k = (k − x % k) % k
0k2k3k x (k − x%k)%k
x sits between multiples; the jump to the next tick is (k - x%k) % k, and it's 0 when x is on a tick.
GoalJava expressionNote
Round down to a multiple of k(x / k) * kinteger division floors
Round up to a multiple of k((x + k - 1) / k) * k+k-1 forces round-up
Ceiling division ⌈x/k⌉(x + k - 1) / k"how many k-buckets hold x"
Steps up to next multiple(k - x % k) % k0 if already a multiple
★ Trick — ceil-divide without floats Never use Math.ceil((double) x / k) — a double can't exactly hold large long values and will round wrong at boundaries (same reason as Rule 3's Math.pow ban). The exact integer form (x + k - 1) / k is faster and correct for every input. Java also has Math.ceilDiv(x, k) (JDK 18+) if you're on a recent version.

Divide and remainder, read as a pair#

The same two operators keep showing up as a clean way to think, not just to compute. For any x and a block size k: x / k tells you which block you're in and x % k tells you where inside it. Almost every "wrap it around", "which bucket", "flatten a grid", or "peel a digit" question is just this one idea in disguise.

You wantExpressionWhy it reads cleanly
Is x even / odd?(x & 1) == 0  /  (x & 1) == 1the last bit is the parity; faster and clearer than x % 2
Next index on a ring of size n(i + 1) % nfrom the last slot it wraps to 0 on its own — no if
Previous index on that ring(i - 1 + n) % nthe + n keeps it positive before the wrap (same guard as Rule 5)
Flatten grid cell (r, c) of width Cidx = r * C + cwalk a 2D grid with a single index
Un-flatten idx back to (r, c)r = idx / C,   c = idx % Cdivision gives the row, remainder gives the column
Last digit / drop itx % 10  /  x /= 10peel digits right-to-left in a loop
Which bucket of size kx / k  (offset x % k)group values into fixed-size ranges
012 345 5 → 0 i = 5, n = 6 (5 + 1) % 6 = 0 the modulo does the wrap for you no edge-case branch to forget
A ring is just indices under % n. Stepping past the end lands back at 0 automatically — the reason circular-array code stays branch-free.
★ Trick — let % n handle the edges Circular buffers, round-robin turns, "rotate an array by k", clock arithmetic — all of them collapse to indexing under % n. Whenever you catch yourself writing if (i == n) i = 0;, replace it with i = (i + 1) % n. Going the other way, guard the negative first: (i - 1 + n) % n.
Worked Problem 1

All 5 rules in one expression#

Compute Ans = (A + ((B − C)D) / (E × 100) − F × G) % (109+7), given 1 ≤ A..G ≤ 109. If the answer is a fraction P/Q, print P · Q-1 % M.

This is the capstone — every rule fires at once. Read it as a pipeline of temp values, each reduced immediately (Rule 2), powers via binary expo (Rule 3), the division as a multiply-by-inverse (Rule 4), and a final positive-print (Rule 5).

t = (B - C) % M t = binpow(t, D) t2 = (E*100) % M t = t * inv(t2) % M t2 = F*G % M t = (A + t) % M t = (t - t2) % M print ((t % M) + M) % M ⚠ Rule 5
Each box reduces immediately. Powers use binary expo; the /(E×100) becomes × inv(t2); the print applies Rule 5.
import java.util.Scanner;

public class Main {
    static long MOD = 1_000_000_007L;

    static long power(long a, long b) {
        a %= MOD; long res = 1;
        while (b > 0) {
            if ((b & 1) == 1) res = res * a % MOD;
            a = a * a % MOD; b >>= 1;
        }
        return res;
    }
    static long inv(long x) { return power(x, MOD - 2); }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        long a = sc.nextLong(), b = sc.nextLong(), c = sc.nextLong();
        long d = sc.nextLong(), e = sc.nextLong();
        long f = sc.nextLong(), g = sc.nextLong();

        long t  = ((b - c) % MOD + MOD) % MOD;   // (B-C), guard negative
        t = power(t, d);                        // (B-C)^D  (Rule 3)
        long t2 = (e % MOD) * 100 % MOD;         // E*100    (Rule 2)
        t = t * inv(t2) % MOD;                  // / (E*100) (Rule 4)
        t2 = f % MOD * (g % MOD) % MOD;         // F*G      (Rule 2)
        t = (a + t) % MOD;                      // + A
        t = (t - t2) % MOD;                     // - F*G
        System.out.println(((t % MOD) + MOD) % MOD);  // Rule 5
    }
}
💡 Why this satisfies "print P · Q-1" Working entirely in mod space with inv() for the division automatically produces P · Q-1 % M — that is the value of an irreducible fraction P/Q under the modulus. You never form the fraction explicitly; the inverse does it for you.
Worked Problem 2

Geometric series sum, mod M#

Compute F(x, n, m) = (1 + x + x2 + ... + xn) % m, with 1 ≤ x, n, m ≤ 109.

Summing term-by-term is O(n) — too slow. Notice this is a geometric progression (GP) with first term 1 and ratio x, so the closed form applies:

1 + x + x2 + ... + xn = (xn+1 − 1) / (x − 1)

Now every rule shows up: the numerator's power needs binary expo (Rule 3), the −1 can go negative (Rule 5), and the division by (x−1) is a multiply-by-inverse (Rule 4). Two edge cases matter.

⚠ Pitfall — two edge cases (1) x = 1: the formula divides by x−1 = 0, which has no inverse. But if x=1 the series is just 1+1+...+1 = n+1 terms, so answer is (n+1) % m. Handle it separately.
(2) m not prime: Fermat's inverse is invalid, so you can't use inv(x-1). Fall back to the O(log n) divide-and-conquer recurrence below, which needs no inverse at all.

Case 1 — m is prime (Fermat inverse works)#

static long gpSumPrime(long x, long n, long m) {
    MOD = m;                                  // power/inv use MOD
    if (x == 1) return (n + 1) % m;         // edge case (1)
    long num = ((power(x, n + 1) - 1) % m + m) % m;  // x^(n+1) - 1, guarded
    long den = ((x - 1) % m + m) % m;          // x - 1, guarded
    long ans = num * inv(den) % m;            // / (x-1) via inverse
    return ((ans % m) + m) % m;               // Rule 5
}

Case 2 — m is not prime#

When you can't invert, avoid division entirely. Split the series in halves. For an even count of terms, S(k terms) = S(k/2) × (1 + xk/2); for odd, peel one term. This is O(log n) and uses only + and ×, so any modulus (prime or not) is fine.

// sum of 1 + x + ... + x^(cnt-1), i.e. cnt terms, mod m. No inverse needed.
static long gpTerms(long x, long cnt, long m) {
    if (cnt == 0) return 0;
    if (cnt == 1) return 1 % m;
    if ((cnt & 1) == 0) {                       // even: pair up the halves
        long half = gpTerms(x, cnt / 2, m);
        long factor = (1 + powMod(x, cnt / 2, m)) % m;
        return half * factor % m;
    } else {                                    // odd: last term + the rest
        return (gpTerms(x, cnt - 1, m) + powMod(x, cnt - 1, m)) % m;
    }
}
// call with cnt = n + 1 terms:  gpTerms(x, n + 1, m)
// powMod is binary exponentiation taking an explicit modulus m
Java note Here powMod(a, b, m) is just the iterative power from Rule 3 with the modulus passed as a parameter instead of the global MOD — because in this problem m comes from input and may differ from case to case.
Cheat flow

How to decide what to do#

Open a problem and run this top to bottom — it's the 5 rules as a checklist.

Sees "mod M" or huge counts? → use long (R1) 3+ factors? → combine two at a time, %M each (R2) A power a^b? → binary expo, never Math.pow (R3) A division "/"? → multiply by inv(b)=b^(M-2) (R4) Any subtraction? → guard, and print ((a%M)+M)%M (R5) modulus not prime? → avoid inverse (Ext. Euclid / D&C)
The five rules, in the order you meet them while coding a solution.

Interview / Practice Q&A#

Click to reveal. Answers sized to read aloud.

Why do problems ask for the answer modulo 109+7 instead of the real number?
Because the true answer often grows factorially and can have hundreds of digits, which no primitive type stores. Everyone reduces mod a fixed prime so answers stay small and comparable. 109+7 is chosen because it's prime (enabling division via inverse) and small enough that the product of two reduced values still fits in a 64-bit long.
How do you keep a value from overflowing when it can exceed a couple billion?
You declare the wide type by hand: use long for the modulus and every running value, and suffix big literals with L. Watch method boundaries — reading input as int and multiplying does the math in int space before widening, so read into long or cast the first operand with (long) a * b.
What does "take two at a time" mean and why is it necessary?
When multiplying three or more values, combine just two, reduce mod M, then bring in the next. In a * b * c, the product a*b can overflow a long before the % M ever runs, and mod can't fix an already-corrupted value. Folding one factor at a time keeps every intermediate below M×M, safely inside a long.
Why never use Math.pow() for modular powers in Java?
Math.pow returns a double, which can't exactly represent large integers and gives no way to reduce mod M during the computation, so it overflows and rounds wrong. Write binary exponentiation instead: square the base and halve the exponent for O(log b), reducing mod M each step. For a bulletproof-but-slower option, BigInteger.modPow works too.
How do you divide under a modulus, and why can't you divide directly?
You multiply by the modular inverse, because taking the remainder of numerator and denominator separately loses the information division needs (2/6 isn't an integer). When M is prime, the inverse of b is b^(M-2) % M by Fermat's little theorem, computed with binary exponentiation. So a / b becomes a * power(b, M-2) % M.
Your answer prints as a negative number. What's the fix?
The % operator returns a negative result when the left operand is negative (-3 % 7 is -3). Wrap the final answer as ((ans % M) + M) % M to force it into [0, M). Math.floorMod(ans, M) is a built-in one-liner that does the same thing.
Walk through the GP-sum problem. What breaks when x = 1 or m isn't prime?
The closed form (x^(n+1) - 1)/(x - 1) divides by x-1. If x=1 that's division by zero, but the series is just n+1 ones, so return (n+1) % m. If m isn't prime, Fermat's inverse is invalid, so avoid division entirely with an O(log n) divide-and-conquer that pairs the halves using only + and ×.
For the sum 1 to n, why halve the even factor before multiplying?
Exactly one of n and n+1 is even, so dividing that one by 2 first keeps the arithmetic exact and roughly halves the peak intermediate value — avoiding overflow that n*(n+1) would cause before the division. If the answer is needed mod a prime and n is enormous, reduce first and multiply by inv(2) instead.
Given x and k, how many steps until x is a multiple of k, and why the outer % k?
It's (k - x % k) % k. The inner x % k is how far past the previous multiple you are, so k minus that is the gap to the next one. The outer % k handles the case where x is already a multiple, returning 0 instead of k.

Key Takeaways#

  1. Overflow is the enemy, not the big number. A Java long caps near 9.2×1018; cross it and values wrap to garbage silently.
  2. Rule 1 — use long everywhere. Type growing values long from the start and suffix big literals with L.
  3. Rule 2 — take two at a time. ((a*b)%M * (c%M))%M; never let three factors multiply before reducing.
  4. Rule 3 — never Math.pow(). Use binary exponentiation, O(log b), reducing each step (or BigInteger.modPow).
  5. Rule 4 — don't divide, invert. a/b → a * b^(M-2) % M when M is prime (Fermat).
  6. Rule 5 — fix negatives on print. ((ans%M)+M)%M, or Java's Math.floorMod(ans, M).
  7. Edge cases bite: x=1 and non-prime moduli break the inverse — special-case them.
  8. Clean-thinking tricks: halve the even factor in n(n+1)/2; jump to the next multiple via (k - x%k)%k; ceil-divide with (x+k-1)/k, never floats; and read / and % as a pair — x/k is the block, x%k the offset (circular index (i+1)%n, grid flatten r*C+c).

The through-line. Every rule here is one defense against the same enemy — a value growing past what a long can hold before you reduce it. Reduce early, square instead of looping, invert instead of dividing, and guard the sign on the way out. Once those become reflexes, modular problems stop being about arithmetic and start being about logic.