Skip to content

Commit 471dd0b

Browse files
Create Just a Simple Sum Explanation.txt
1 parent 37ab0b6 commit 471dd0b

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
Firstly, let us notice that M is small but n is very large
2+
3+
If we have to find the answer, we have to do in terms of m, not n.
4+
5+
Let us write the series like this
6+
7+
(1^1 + 2^2 + 3^3 + .... + m^m) +
8+
((m + 1)^{m + 1} + (m + 2)^{m + 2} + (m + 3)^{m + 3} + ... + (2m)^{2m}) +
9+
.
10+
.
11+
.
12+
13+
We can notice that we can write the series as a sum of M geometric progressions
14+
15+
since (m + i)^x = i^x (mod m)
16+
17+
-----
18+
19+
We have to sum M series like
20+
21+
(1^1 + 1^{m + 1} + 1^{2m + 1} + ... + ) +
22+
(2^2 + 2^{m + 2} + 2^{2m + 2} + ... + ) +
23+
.
24+
.
25+
((m - 1)^{m - 1} + (m - 1)^{2m - 1) + .... + )
26+
27+
The i-th geometric series has
28+
29+
1. First term - i^i
30+
2. Difference - i^M
31+
3. Number of terms - Number of integers = i (mod M) <= N
32+
33+
-----
34+
35+
void solve()
36+
{
37+
long long n, mod;
38+
cin >> n >> mod;
39+
40+
long long sum = 0;
41+
for(int i = 1; i <= min(n, mod - 1); i++)
42+
{
43+
long long first_term = power(i, i, mod);
44+
long long multiplier = power(i, mod, mod);
45+
long long no_of_terms = (n/mod) + (n%mod >= i);
46+
47+
sum += first_term*geometric_progression(multiplier, no_of_terms, mod);
48+
sum %= mod;
49+
}
50+
51+
cout << sum << "\n";
52+
}
53+
54+
------
55+
56+
How to find the sum of a geometric series quickly ?
57+
58+
We cannot use the normal expression S = a(r^n - 1)/(r - 1)
59+
60+
since we need to calculate the inverse of (r - 1) mod M
61+
62+
M is not guaranteed to be prime so we cannot raise the denominator to (M - 1) to get the inverse.
63+
64+
M is large so we cannot calculate phi(M) to invoke Fermat's Little Theorem at all.
65+
66+
Instead, we will use another beautiful method to evaluate the sum of a GP without division.
67+
68+
-----
69+
70+
S = 1 + r + r^2 + r^3 + .... + r^n
71+
72+
Group (1 + r) terms
73+
74+
S = (1 + r) + (r^2 + r^3) + (r^4 + r^5) + ....
75+
76+
S = (1 + r) + r^2(1 + r) + r^4(1 + r) + ...
77+
78+
S = (1 + r)(1 + r^2 + r^4 + ... )
79+
80+
So if the sum of a geometric series of N terms with difference r is G(r, n)
81+
82+
G(r, n) = (1 + r)G(r^2, n/2)
83+
84+
When there are an odd number of terms, then one power will be left out after factorizing by (1 + r)
85+
86+
G(r, n) = (1 + r)G(r^2, n/2) + r^n
87+
88+
We have reduced the problem of finding the sum of a term with N terms to a
89+
smaller version of itself of finding the sum of a smaller series of N/2 terms
90+
91+
This will take O(log N) iterations to compute !
92+
93+
This is a very beautiful method.
94+
95+
------
96+
97+
long long geometric_progression(long long multiplier, long long no_of_terms, int mod)
98+
{
99+
//cout << "GP m = " << multiplier << " N = " << no_of_terms << "\n";
100+
if(no_of_terms == 1)
101+
{
102+
return 1;
103+
}
104+
105+
if(no_of_terms == 2)
106+
{
107+
return (1 + multiplier)%mod;
108+
}
109+
110+
long long left_over_power = 0;
111+
112+
if(no_of_terms%2 == 1)
113+
{
114+
left_over_power = power(multiplier, no_of_terms - 1, mod);
115+
}
116+
117+
long long square_multiplier = power(multiplier, 2, mod);
118+
119+
long long factored_gp = geometric_progression(square_multiplier, no_of_terms/2, mod);
120+
long long answer = (1 + multiplier)*factored_gp + left_over_power;
121+
122+
123+
return answer%mod;
124+
}

0 commit comments

Comments
 (0)