Open In App

Find sum of Modulo Power till Y

Improve
Improve
Like Article
Like
Save
Share
Report

Given three positive integers X, Y, Z. Find  (X0+X1+X2+X3+X4+…………………..+Xy-1) % Z.

Examples:

Input: X = 4, Y = 5, Z = 6
Output: 5
Explanation: 40+41+42+43+44 = 1+4+16+64+256 = 341, 341%6 = 5, So 5 is the output

Input: X = 20000, Y = 35000,  Z = 2555
Output: 791

Approach: This can be solved with the following idea:

  • In this approach we have to calculate the value of the function f(y) = x1 * (x2 + 1) * (x4 + 1) * … * (x2^K+ 1) % z, where k is the largest power of 2 that is less than or equal to y.
  • To solve this problem, we can use a greedy approach where we calculate the values of the function for each power of 2 less than or equal to x and then combine them to get the final answer. We can use a vector to store the values of the function and their corresponding powers of 2 and then iterate through this vector in reverse order to add up the terms that we need. 
  • We can also use the fast power algorithm to calculate the powers of a modulo m efficiently.

Proof of the approach:

To prove the correctness of this approach, we have to show that the function f(y) can be calculated by combining the values of the function for each power of 2 less than or equal to y.

  • Let’s consider the value of the function f(y) for a given y. We can express y as a sum of powers of 2, where each power of 2 appears at most once. Let k be the largest power of 2 that is less than or equal to y. Then we have:    y = 2k+r , where 0 ≤ r < 2k.
  • Using this representation of y, we can express f(y) as: f(y) = x1 * (x2 + 1) * (x4 + 1) * … * (x2^k+1) * (x2^(k-1)+1)^(r/2k-1) * … * (x2^2+1)^(r/4) * (x2+1)^(r/2) * x1^(r), where r/2^i denotes the floor division of r by 2^i.
  • Note that each term in this expression corresponds to a power of 2 less than or equal to y. The first k terms correspond to the powers of 2 up to 2^k, and the remaining terms correspond to the powers of 2 between 2^k and y.
  • Using the fast power algorithm, we can efficiently compute each term in this expression. We can store the values of the function and their corresponding powers of 2 in a vector and iterate through this vector in reverse order to add up the terms that we need.
  • Therefore, we have shown that the function f(y) can be calculated by combining the values of the function for each power of 2 less than or equal to y, using the approach described.

Below are the steps for the above approach:

  • Initialize a vector of pairs of integers called v.
  • Loop through the powers of 2 less than or equal to y 
    • Append a new pair to v consisting of the value of the function for the current power of 2 and the power of 2 itself.
    • Update the value of the function for the next power of 2 using the formula current = current * (pow (x, i, z) + 1) % z.
  • Initialize integer variables ‘ans‘ and ‘res‘ to 0.
  • Loop through the pairs in ‘v‘ in reverse order:
    • Remove the last pair from ‘v’ and assign it to ‘temp’.
    • If y is less than temp.second, skip to the next iteration.
    • Update ans = (ans + pow(x, res, z) * temp.first) % z.
    • Update res = temp.second.
    • Subtract the second element of ‘temp’ from y.
  • Print the final value of ‘ans’.

Below is the implementation of the above code:

C++




// C++ code of the above approach
#include <bits/stdc++.h>
#define int long long
using namespace std;
 
// Define the power function with
// parameters 'a', 'b', and 'm'
int pow(int a, int b, int m)
{
 
    // If b is 0, return 1
    if (!b)
        return 1;
 
    // Initialize a temporary variable
    // to 1
    int temp = 1;
 
    // Loop through the binary digits of
    // 'b' in reverse order
    for (int current = a; b;
         b >>= 1, current = current * current % m)
 
        // If the  bit of 'b' is 1, multiply
        // 'temp' by 'current' modulo 'm'
        if (b & 1)
            temp = temp * current % m;
 
    return temp;
}
 
void getValue(int x, int y, int z)
{
 
    vector<pair<int, int> > v;
 
    // Loop through the powers of 2 less
    // than or equal to 'y'
    for (int i = 1, current = 1; i <= y; i <<= 1) {
 
        // Append a new pair to 'v'
        // consisting of 'current' and 'i'
        v.push_back({ current, i });
 
        // Update 'current' to be 'current'
        // times 'x' to the power of 'i'
        // modulo 'z' plus 1 modulo 'z'
        current = current * (pow(x, i, z) + 1) % z;
    }
 
    int ans = 0, res = 0;
 
    // Loop through the pairs in 'v' in
    // reverse order
    while (v.size() > 0) {
 
        // Remove the last pair from 'v'
        // and assign it to 'temp'
        pair<int, int> temp = v.back();
        v.pop_back();
 
        // If 'y' is less than the second
        // element of 'temp', skip to the
        // next iteration
        if (y < temp.second)
            continue;
 
        // Update 'ans' to be 'ans' plus
        // 'x' to the power of 'res'
        // modulo 'z' times the first
        // element of 'tmp' modulo 'z'
        ans = (ans + pow(x, res, z) * temp.first) % z;
 
        // Update 'res' to be 'res' plus
        // the second element of 'temp'
        res += temp.second;
 
        // Subtract the second element of
        // 'temp' from 'y'
        y -= temp.second;
    }
 
    cout << ans << endl;
}
 
// Driver Code
signed main()
{
 
    int x = 20000, y = 35000, z = 2555;
 
    // Function call
    getValue(x, y, z);
    return 0;
}


Java




// Java code implementation:
 
import java.io.*;
import java.util.*;
 
// class pair
class pair {
    int first, second;
    pair(int first, int second)
    {
        this.first = first;
        this.second = second;
    }
}
 
class GFG {
 
    // Define the power function with parameters 'a', 'b',
    // and 'm'
    static long pow(long a, long b, long m)
    {
        // If b is 0, return 1
        if (b == 0)
            return 1;
 
        // Initialize a temporary variable to 1
        long temp = 1;
 
        // Loop through the binary digits of 'b' in reverse
        // order
        for (long current = a; b != 0;
             b >>= 1, current = current * current % m)
 
            // If the  bit of 'b' is 1, multiply 'temp' by
            // 'current' modulo 'm'
            if ((b & 1) == 1)
                temp = temp * current % m;
 
        return temp;
    }
 
    static void getValue(int x, int y, int z)
    {
 
        List<pair> v = new ArrayList<pair>();
 
        // Loop through the powers of 2 less than or equal
        // to 'y'
        for (int i = 1, current = 1; i <= y; i <<= 1) {
 
            // Append a new pair to 'v' consisting of
            // 'current' and 'i'
            v.add(new pair(current, i));
 
            // Update 'current' to be 'current' times 'x' to
            // the power of 'i' modulo 'z' plus 1 modulo 'z'
            current = (int)((long)current
                            * (pow(x, i, z) + 1) % z);
        }
 
        int ans = 0, res = 0;
 
        // Loop through the pairs in 'v' in reverse order
        while (v.size() > 0) {
 
            // Remove the last pair from 'v' and assign it
            // to 'temp'
            pair temp = v.get(v.size() - 1);
            v.remove(v.size() - 1);
 
            // If 'y' is less than the second element of
            // 'temp', skip to the next iteration
            if (y < temp.second)
                continue;
 
            // Update 'ans' to be 'ans' plus 'x' to the
            // power of 'res' modulo 'z' times the first
            // element of 'tmp' modulo 'z'
            ans = (int)((long)ans
                        + pow(x, res, z) * temp.first % z)
                  % z;
 
            // Update 'res' to be 'res' plus the second
            // element of 'temp'
            res += temp.second;
 
            // Subtract the second element of 'temp' from
            // 'y'
            y -= temp.second;
        }
 
        System.out.println(ans);
    }
 
    public static void main(String[] args)
    {
        int x = 20000, y = 35000, z = 2555;
 
        // Function call
        getValue(x, y, z);
    }
}
 
// This code is contributed by sankar.


Python3




# Define the power function with
# parameters 'a', 'b', and 'm'
def pow(a, b, m):
    # If b is 0, return 1
    if b == 0:
        return 1
 
    # Initialize a temporary variable
    # to 1
    temp = 1
 
    # Loop through the binary digits of 'b' in reverse order
    while b > 0:
        # If the bit of 'b' is 1, multiply 'temp' by 'a' modulo 'm'
        if b & 1:
            temp = (temp * a) % m
 
        # Update 'a' to be 'a' squared modulo 'm'
        a = (a * a) % m
 
        # Right shift 'b' by 1
        b >>= 1
 
    return temp
 
def getValue(x, y, z):
    v = []
 
    # Loop through the powers of 2 less than or equal to 'y'
    current = 1
    i = 1
    while i <= y:
        # Append a new pair to 'v' consisting of 'current' and 'i'
        v.append((current, i))
 
        # Update 'current' to be 'current' times 'x' to the
        # power of 'i' modulo 'z' plus 1 modulo 'z'
        current = (current * (pow(x, i, z) + 1)) % z
 
        # Left shift 'i' by 1
        i <<= 1
 
    ans = 0
    res = 0
 
    # Loop through the pairs in 'v' in reverse order
    while v:
        # Remove the last pair from 'v' and assign it to 'temp'
        temp = v.pop()
 
        # If 'y' is less than the second element of 'temp',
        # skip to the next iteration
        if y < temp[1]:
            continue
 
        # Update 'ans' to be 'ans' plus 'x' to the power of 'res'
        # modulo 'z' times the first element of 'temp' modulo 'z'
        ans = (ans + pow(x, res, z) * temp[0]) % z
 
        # Update 'res' to be 'res' plus the second element of 'temp'
        res += temp[1]
 
        # Subtract the second element of 'temp' from 'y'
        y -= temp[1]
 
    print(ans)
 
# Driver Code
x = 20000
y = 35000
z = 2555
 
# Function call
getValue(x, y, z)


C#




// C# code of the above approach
using System;
using System.Collections.Generic;
 
class Pair
{
    public int First { get; set; }
    public int Second { get; set; }
 
    public Pair(int first, int second)
    {
        First = first;
        Second = second;
    }
}
 
class GFG
{
  // Define the power function with parameters 'a', 'b',
 // and 'm'
    static long Pow(long a, long b, long m)
    {
      // If b is 0, return 1
        if (b == 0)
            return 1;
 
       // Initialize a temporary variable to 1
        long temp = 1;
 
         // Loop through the binary digits of 'b' in reverse
        // order
        for (long current = a; b != 0; b >>= 1, current = current * current % m)
        {
            if ((b & 1) == 1)
                temp = temp * current % m;
        }
 
        return temp;
    }
 
    static void GetValue(int x, int y, int z)
    {
        List<Pair> v = new List<Pair>();
 
         // Loop through the powers of 2 less than or equal
        // to 'y'
        for (int i = 1, current = 1; i <= y; i <<= 1)
        {
            v.Add(new Pair(current, i));
            current = (int)((long)current * (Pow(x, i, z) + 1) % z);
        }
 
        int ans = 0, res = 0;
 
        while (v.Count > 0)
        {
            Pair temp = v[v.Count - 1];
            v.RemoveAt(v.Count - 1);
 
            if (y < temp.Second)
                continue;
            // Update 'ans' to be 'ans' plus 'x' to the
            // power of 'res' modulo 'z' times the first
            // element of 'tmp' modulo 'z'
            ans = (int)((long)ans + Pow(x, res, z) * temp.First % z) % z;
            res += temp.Second;
            y -= temp.Second;
        }
 
        Console.WriteLine(ans);
    }
 
    static void Main(string[] args)
    {
        int x = 20000, y = 35000, z = 2555;
 
        // Function call
        GetValue(x, y, z);
    }
}
// this code is contributed by codearcade


Javascript




// Javascript code of following approach
// Define the power function with
// parameters 'a', 'b', and 'm'
function pow(a, b, m) {
    // If b is 0, return 1
    if (b === 0) {
        return 1;
    }
 
    // Initialize a temporary variable
    // to 1
    let temp = 1;
 
    // Loop through the binary digits of 'b' in reverse order
    while (b > 0) {
        // If the bit of 'b' is 1, multiply 'temp' by 'a' modulo 'm'
        if (b & 1) {
            temp = (temp * a) % m;
        }
 
        // Update 'a' to be 'a' squared modulo 'm'
        a = (a * a) % m;
 
        // Right shift 'b' by 1
        b >>= 1;
    }
 
    return temp;
}
 
function getValue(x, y, z) {
    let v = [];
 
    // Loop through the powers of 2 less than or equal to 'y'
    let current = 1;
    let i = 1;
    while (i <= y) {
        // Append a new pair to 'v' consisting of 'current' and 'i'
        v.push([current, i]);
 
        // Update 'current' to be 'current' times 'x' to the
        // power of 'i' modulo 'z' plus 1 modulo 'z'
        current = (current * (pow(x, i, z) + 1)) % z;
 
        // Left shift 'i' by 1
        i <<= 1;
    }
 
    let ans = 0;
    let res = 0;
 
    // Loop through the pairs in 'v' in reverse order
    while (v.length > 0) {
        // Remove the last pair from 'v' and assign it to 'temp'
        let temp = v.pop();
 
        // If 'y' is less than the second element of 'temp',
        // skip to the next iteration
        if (y < temp[1]) {
            continue;
        }
 
        // Update 'ans' to be 'ans' plus 'x' to the power of 'res'
        // modulo 'z' times the first element of 'temp' modulo 'z'
        ans = (ans + pow(x, res, z) * temp[0]) % z;
 
        // Update 'res' to be 'res' plus the second element of 'temp'
        res += temp[1];
 
        // Subtract the second element of 'temp' from 'y'
        y -= temp[1];
    }
 
    console.log(ans);
}
 
// Driver Code
let x = 20000;
let y = 35000;
let z = 2555;
 
// Function call
getValue(x, y, z);
 
// This code is contributed by Dwaipayan Bandyopadhyay


Output

791







Time Complexity: O(log(y) * log(x))
Auxiliary Space: O(log y)



Last Updated : 21 Aug, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads