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.
The whole page on one screen. Everything here is unpacked in full below. Watch for the marked lines: ★ trick · ⚠ pitfall · 💡 tip.
a % m = remainder after dividing a by m → range
0 .. m-1int = 32-bit, max ~2.1e9long = 64-bit, max ~9.2e18long from the start1_000_000_007L (note the L)M+M < int, M*M < longlong everywhere; mod = 1_000_000_007L
((a*b)%M * (c%M))%Ma*b*c overflows before %
ever runsMath.pow() (double!) → binary expo((ans % M) + M) % M kills negativesMath.floorMod(a, M)
(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/2))^2a * a^(b-1)a^(M-1) % M = 1 → a * a^(M-2) = 1
inv(a) = binpow(a, M-2) ← a^-1(a/b)%M = a * inv(b) % Mn(n+1)/2; halve the EVEN one first(k - x%k) % k(x + k - 1) / kMath.ceil((double)x/k) for big longs
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.
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.
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.
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.
int vs long, and the L suffixOverflow 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.
| Type | Holds up to | Named 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 |
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).
109+7 is often called a "sweet spot." Two properties earn it that name.
| Property | What it buys you |
|---|---|
| It's prime | Every 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 size | Any 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. |
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.
long everywhereThe 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
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.
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.
M×M,
safely inside a long.// 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
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.
Math.pow() — binary
exponentiationMath.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.
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.
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;
}
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;
}
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.
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.
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
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.
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.
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.
(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);
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.
n(n+1)/2 trapThe 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.
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);
}
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.
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.
(k - x%k) % k, and it's 0
when x is on a tick.| Goal | Java expression | Note |
|---|---|---|
| Round down to a multiple of k | (x / k) * k |
integer 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) % k |
0 if already a multiple |
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.
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 want | Expression | Why it reads cleanly |
|---|---|---|
Is x even / odd? |
(x & 1) == 0 / (x & 1) == 1 |
the last bit is the parity; faster and clearer than x % 2 |
Next index on a ring of size n |
(i + 1) % n |
from the last slot it wraps to 0 on its own — no if |
| Previous index on that ring | (i - 1 + n) % n |
the + n keeps it positive before the wrap (same guard as Rule 5) |
Flatten grid cell (r, c) of width C |
idx = r * C + c |
walk a 2D grid with a single index |
Un-flatten idx back to (r, c) |
r = idx / C, c = idx % C |
division gives the row, remainder gives the column |
| Last digit / drop it | x % 10 / x /= 10 |
peel digits right-to-left in a loop |
Which bucket of size k |
x / k (offset x % k) |
group values into fixed-size ranges |
% n. Stepping past the end lands back at
0 automatically — the reason circular-array code stays branch-free.% 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.
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).
/(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
}
}
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.
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:
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.
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.inv(x-1). Fall back to the
O(log n) divide-and-conquer recurrence below, which needs no inverse at all.
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
}
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
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.
Open a problem and run this top to bottom — it's the 5 rules as a checklist.
Click to reveal. Answers sized to read aloud.
long.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.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.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.
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.% 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.(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 ×.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.(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.long caps near
9.2×1018; cross it and values wrap to garbage silently.long everywhere. Type growing values long from
the start and suffix big literals with L.((a*b)%M * (c%M))%M; never let three factors
multiply before reducing.Math.pow(). Use binary exponentiation,
O(log b), reducing each step (or BigInteger.modPow).a/b → a * b^(M-2) % M when M is prime
(Fermat).((ans%M)+M)%M, or Java's
Math.floorMod(ans, M).x=1 and non-prime moduli break the inverse — special-case
them.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.