Sequences with Nice Divisibility Properties
Let S(n, k, m) denote the number of n -tuples (a_1, a_2,..., a_n) of positive integers satisfying: 1. 1 <= a_i <= m for all 1 <= i <= n. 2. a_1 + a_2 +... + a_n equiv 0 (mod k). Compute S(n, k, m)...
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Let $Seq(n,k)$ be the number of positive-integer sequences $\{a_i\}_{1 \le i \le n}$ of length $n$ such that:
$n$ is divisible by $a_i$ for $1 \le i \le n$, and
$n + a_1 + a_2 + \cdots + a_n$ is divisible by $k$.
Example:
$Seq(3,4) = 4$, and the $4$ sequences are: \begin{align*} \{1, 1, 3\} \\ \{1, 3, 1\} \\ \{3, 1, 1\} \\ \{3, 3, 3\} \end{align*}
$Seq(4,11) = 8$, and the $8$ sequences are: \begin{align*} \{1, 1, 1, 4\} \\ \{1, 1, 4, 1\} \\ \{1, 4, 1, 1\} \\ \{4, 1, 1, 1\} \\ \{2, 2, 2, 1\} \\ \{2, 2, 1, 2\} \\ \{2, 1, 2, 2\} \\ \{1, 2, 2, 2\} \end{align*}
The last nine digits of $Seq(1111,24)$ are $840643584$.
Find the last nine digits of $Seq(1234567898765,4321)$.
Problem 511: Sequences with Nice Divisibility Properties
Mathematical Foundation
Definition 1. Let denote a fixed primitive -th root of unity. For , define the character sum
Theorem 1 (Roots of Unity Filter). For any integer ,
where denotes the Iverson bracket (1 if is true, 0 otherwise).
Proof. We distinguish two cases.
Case 1: . Then , so for every . The sum equals , and .
Case 2: . Then . The sum is a geometric series with ratio :
In both cases the identity holds.
Theorem 2 (Counting Formula). With the notation above,
Proof. By definition,
Substituting the identity from Theorem 1:
Since all sums are finite, we may exchange the order of summation (Fubini’s theorem for finite sums):
The factorization into a product holds because the exponent separates multiplicatively, and the constraint on each is identical and independent.
Lemma 1 (Closed Form for ). For :
Proof. When , every term , so .
When , we have (since is a primitive -th root). The sum is a finite geometric series with first term , common ratio , and terms. By the standard geometric series formula:
Corollary 1 (Special Case ). When , we have .
Proof. For : . For : . More directly, for (by Theorem 1 with ), so . Therefore .
A combinatorial verification: choose freely ( ways), then is uniquely determined as the element of satisfying .
Proposition 1 (Modular Arithmetic Realization). Suppose is a prime with . Let be a primitive root modulo and set . Then is a primitive -th root of unity in , and the formula from Theorem 2 can be evaluated entirely in :
where is the modular analogue of , computed using in place of .
Proof. Since has order in , the element has order exactly , hence is a primitive -th root of unity in . The algebraic identities in Theorems 1, 2, and Lemma 1 hold over any field containing such a root, in particular over . Division by is well-defined since (as and is prime).
Editorial
Count n-tuples (a_1,…,a_n) with 1 <= a_i <= m and sum divisible by k. Uses the roots-of-unity filter (discrete Fourier transform technique). We precondition: p prime, k | (p - 1). Finally, else.
Pseudocode
Precondition: p prime, k | (p - 1)
else
Complexity Analysis
- Time: . The loop iterates times; within each iteration, computing costs via binary exponentiation.
- Space: auxiliary beyond the input.
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod_pow(ll base, ll exp, ll mod) {
ll result = 1;
base %= mod;
while (exp > 0) {
if (exp & 1) result = (__int128)result * base % mod;
base = (__int128)base * base % mod;
exp >>= 1;
}
return result;
}
ll mod_inv(ll a, ll mod) {
return mod_pow(a, mod - 2, mod);
}
// Find primitive root of prime p
ll primitive_root(ll p) {
ll phi = p - 1;
// Factor phi
vector<ll> factors;
ll n = phi;
for (ll d = 2; d * d <= n; d++) {
if (n % d == 0) {
factors.push_back(d);
while (n % d == 0) n /= d;
}
}
if (n > 1) factors.push_back(n);
for (ll g = 2; g < p; g++) {
bool ok = true;
for (ll f : factors) {
if (mod_pow(g, phi / f, p) == 1) {
ok = false;
break;
}
}
if (ok) return g;
}
return -1;
}
// S(n, k, m) mod p using roots of unity filter
// Requires k | (p-1)
ll S_mod(ll n, ll k, ll m, ll p) {
assert((p - 1) % k == 0);
ll g = primitive_root(p);
ll omega = mod_pow(g, (p - 1) / k, p);
ll inv_k = mod_inv(k, p);
ll total = 0;
for (ll j = 0; j < k; j++) {
ll gj;
if (j == 0) {
gj = m % p;
} else {
ll w = mod_pow(omega, j, p);
ll wm = mod_pow(w, m, p);
// gj = w * (1 - w^m) / (1 - w)
ll num = w % p * ((1 - wm % p + p) % p) % p;
ll den = (1 - w % p + p) % p;
gj = num % p * mod_inv(den, p) % p;
}
total = (total + mod_pow(gj, n, p)) % p;
}
return total % p * inv_k % p;
}
int main() {
// Simple case: S(n, k) = k^(n-1) when m = k
cout << "Simple case verification:" << endl;
for (int n = 1; n <= 5; n++) {
for (int k : {2, 3, 5}) {
ll result = 1;
for (int i = 0; i < n - 1; i++) result *= k;
cout << " S(" << n << ", " << k << ") = " << result << endl;
}
}
// General case with modular arithmetic
ll p = 1000000007; // 10^9 + 7
ll k = 7;
// Check k | (p-1): (10^9 + 6) % 7 = ?
if ((p - 1) % k == 0) {
ll n = 100, m = 20;
ll result = S_mod(n, k, m, p);
cout << "\nS(" << n << ", " << k << ", " << m << ") mod " << p
<< " = " << result << endl;
}
return 0;
}
"""
Problem 511: Sequences with Nice Divisibility Properties
Count n-tuples (a_1,...,a_n) with 1 <= a_i <= m and sum divisible by k.
Uses the roots-of-unity filter (discrete Fourier transform technique).
"""
import numpy as np
from math import gcd
def S_simple(n: int, k: int):
"""
Count n-tuples from {1,...,k} with sum divisible by k.
Answer: k^(n-1) (since choosing n-1 values freely determines the last).
"""
return pow(k, n - 1)
def S_general_float(n: int, k: int, m: int):
"""
Count n-tuples from {1,...,m} with sum divisible by k.
Uses roots-of-unity filter with floating-point arithmetic.
For exact results, use modular arithmetic version.
"""
omega = np.exp(2j * np.pi / k)
total = 0.0
for j in range(k):
if j == 0:
gj = m
else:
w = omega ** j
# g_j = sum_{a=1}^{m} w^a = w * (1 - w^m) / (1 - w)
gj = w * (1 - w ** m) / (1 - w)
total += gj ** n
result = total / k
return int(round(result.real))
def S_general_mod(n: int, k: int, m: int, p: int):
"""
Count n-tuples from {1,...,m} with sum divisible by k, modulo prime p.
Requires k | (p - 1) so that a k-th root of unity exists mod p.
"""
# Find a primitive k-th root of unity mod p
# First find a primitive root mod p, then take its ((p-1)/k)-th power
assert (p - 1) % k == 0, f"k={k} does not divide p-1={p-1}"
# Find primitive root of p
def primitive_root(p):
if p == 2:
return 1
phi = p - 1
# Factor phi
factors = set()
n = phi
for d in range(2, int(n**0.5) + 1):
while n % d == 0:
factors.add(d)
n //= d
if n == 1:
break
if n > 1:
factors.add(n)
for g in range(2, p):
ok = True
for f in factors:
if pow(g, phi // f, p) == 1:
ok = False
break
if ok:
return g
return -1
g = primitive_root(p)
omega = pow(g, (p - 1) // k, p)
total = 0
inv_k = pow(k, p - 2, p) # modular inverse of k
for j in range(k):
if j == 0:
gj = m % p
else:
w = pow(omega, j, p)
wm = pow(w, m, p)
# gj = w * (1 - w^m) / (1 - w) mod p
num = w * (1 - wm) % p
den = (1 - w) % p
gj = num * pow(den, p - 2, p) % p
total = (total + pow(gj, n, p)) % p
return total * inv_k % p
def brute_force(n: int, k: int, m: int):
"""Brute-force for small n, m: enumerate all tuples."""
if n == 0:
return 1 if 0 % k == 0 else 0
count = 0
def recurse(depth, running_sum):
nonlocal count
if depth == n:
if running_sum % k == 0:
count += 1
return
for a in range(1, m + 1):
recurse(depth + 1, running_sum + a)
recurse(0, 0)
return count
# Verify simple case
print("Simple case S(n, k) = k^(n-1):")
for n in range(1, 6):
for k in [2, 3, 5]:
exact = brute_force(n, k, k)
formula = S_simple(n, k)
status = "OK" if exact == formula else "MISMATCH"
print(f" S({n}, {k}) = {formula} (brute={exact}) [{status}]")
# Verify general case
print("\nGeneral case S(n, k, m):")
for n, k, m in [(2, 3, 5), (3, 4, 6), (2, 5, 7), (3, 3, 4)]:
exact = brute_force(n, k, m)
approx = S_general_float(n, k, m)
status = "OK" if exact == approx else f"MISMATCH(got {approx})"
print(f" S({n}, {k}, {m}) = {exact} (float={approx}) [{status}]")
# Modular computation for larger values
# Need p such that k | (p-1)
# For k=1234567, we need p with (p-1) % 1234567 == 0
# Example with moderate k
k_test = 7
n_test = 100
m_test = 20
p_mod = 10**9 + 7 # (10^9+6) % 7 = (10^9+6) mod 7
# Check if 7 | (p-1)
if (p_mod - 1) % k_test == 0:
result_mod = S_general_mod(n_test, k_test, m_test, p_mod)
result_float = S_general_float(n_test, k_test, m_test)
print(f"\nS({n_test}, {k_test}, {m_test}) mod {p_mod} = {result_mod}")
else:
print(f"\nCannot use p={p_mod} for k={k_test} (k does not divide p-1)")