# HackerRank Polynomial Division problem solution

In this HackerRank Polynomial Division problem, we have given the values of n, a,b and q queries, perform each query in order.

## Problem solution in Python programming.

```#!/bin/python3

import math
import os
import random
import re
import sys

# returns d, x, y so that gcd(a, b) = d and ax + by = d
def extended_euclidean_alg(a,b):
# starts out as p[0] = P_{-1}, p[1] = P_0 and same for q
# in general it's the previous 2 terms, P_{i-1}, P_{i-2}
p = [0, 1]
q = [1, 0]
counter = 1
while b != 0:
quo = a//b
rem = a % b
newP = quo*p[1] + p[0]
newQ = quo*q[1] + q[0]
p[0] = p[1]
p[1] = newP
q[0] = q[1]
q[1] = newQ
a = b
b = rem
counter = (counter + 1) % 2
minusOne = (counter-1) % 2
return a, q[0]*((-1)**minusOne), p[0]*((-1)**(counter))

def leastSigBit(num):
return (num & -num)

# implementation of a Fenwick tree
class PrefixSumTree(object):
def __init__(self,array):
l = len(array)
self.sums = [0] * l
for i in range(1,l):
cl = i - leastSigBit(i)
for j in range(cl+1,i+1):
self.sums[i] = (self.sums[i] + array[j]) % p

def sum(self,i):
sum = 0
while i > 0:
sum = (sum + self.sums[i]) % p
i -= leastSigBit(i)
return sum

while i <= len(self.sums)-1:
self.sums[i] = (self.sums[i] + toAdd) % p
i += leastSigBit(i)

p = 10**9 + 7

def polynomialDivision(a, b, c, queries):
res = []
a_inv = extended_euclidean_alg(p, a)[2]
x = -b*a_inv % p
# if x != 0 then we have to build the sum tree
if x != 0:
l = len(c)
# polyArray[i+1] = c[i]*x^i % p and polyArray[0] = 0
polyArray = [0] * (l+1)
polyArray[1] = c[0]
# powsOfX[i] = x^i % p
powsOfX = [1] * l
for i in range(1,l):
newPow = (powsOfX[i-1]*x) % p
powsOfX[i] = newPow
polyArray[i+1] = (c[i]*newPow) % p
sumTree = PrefixSumTree(polyArray)
for q in queries:
if q[0] == 1:
# compute how much we need to add for the sum
# update the array c with our new entry q[2]
c[q[1]] = q[2]
if x != 0:
# then we add the appropriate amount to our prefix sums.
# since sumTree keeps track of sum c_i * x^i we multiply by the
# appropriate power of x
else:
# remember c is zero indexed but sumTree is one indexed
# so we do sum(q[2]+1) - sum(q[1]) instead of sum(q[2]) - sum(q[1]-1)
pOfX = c[q[1]] if x == 0 else (sumTree.sum(q[2]+1) - sumTree.sum(q[1])) % p
if pOfX == 0:
res.append("Yes")
else:
res.append("No")
return res

if __name__ == '__main__':
fptr = open(os.environ['OUTPUT_PATH'], 'w')

nabq = input().split()

n = int(nabq[0])

a = int(nabq[1])

b = int(nabq[2])

q = int(nabq[3])

c = [int(t) for t in input().rstrip().split()]

queries = []

for _ in range(q):
queries.append([int(t) for t in input().rstrip().split()])

result = polynomialDivision(a, b, c, queries)

fptr.write('\n'.join(result))
fptr.write('\n')

fptr.close()```

## Problem solution in Java Programming.

```import java.io.*;
import java.util.*;

public class Solution {

static final int MOD = 1_000_000_007;

static class SegmentTree {
int st[];
int n;

public SegmentTree(int n) {
this.n = n;
int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));

int maxSize = 2 * (int) Math.pow(2, x) - 1;
st = new int[maxSize];
}

int getMid(int s, int e) {
return s + (e - s) / 2;
}

long getSum(int ss, int se, int qs, int qe, int si) {
if (qs <= ss && qe >= se) {
return st[si];
}

if (se < qs || ss > qe) {
return 0;
}

int mid = getMid(ss, se);
return sum(getSum(ss, mid, qs, qe, 2 * si + 1),
getSum(mid + 1, se, qs, qe, 2 * si + 2));
}

void updateValue(int ss, int se, int i, int diff, int si) {
if (i < ss || i > se) {
return;
}

st[si] = (int) sum(st[si], diff);
if (se != ss) {
int mid = getMid(ss, se);
updateValue(ss, mid, i, diff, 2 * si + 1);
updateValue(mid + 1, se, i, diff, 2 * si + 2);
}
}

void updateValue(int arr[], int i, int newVal) {
int diff = newVal - arr[i];

arr[i] = newVal;

updateValue(0, n - 1, i, diff, 0);
}

long getSum(int qs, int qe) {
return getSum(0, n - 1, qs, qe, 0);
}

void construct(int arr[]) {
construct(arr, 0, arr.length - 1, 0);
}

int construct(int arr[], int ss, int se, int si) {
if (ss == se) {
st[si] = arr[ss];
return arr[ss];
}

int mid = getMid(ss, se);
st[si] = (int) sum(construct(arr, ss, mid, si * 2 + 1),
construct(arr, mid + 1, se, si * 2 + 2));
return st[si];
}

}

static long mul(long a, long b) {
return (a * b) % MOD;
}

static long sum(long a, long b) {
return (a + b) % MOD;
}

public static long power(long a, long n) {
if (n < 0) {
return power(power(a, MOD - 2), -n);
}
if (n == 0) {
return 1;
}
if (n == 1) {
return a;
}

long r = 1;
for (; n > 0; n >>= 1, a = (a*a) % MOD) {
if ((n & 1) > 0) {
r = (r*a) % MOD;
}
}
return r;
}

public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));

int n = Integer.parseInt(st.nextToken());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int q = Integer.parseInt(st.nextToken());

if (b > 0) {
int[] pw = new int[n+1];

long coef = (MOD - mul(b, power(a, MOD - 2))) % MOD;
pw[0] = 1;
for (int i = 1; i <= n; i++) {
pw[i] = (int) mul(pw[i - 1], coef);
}

int[] p = new int[n];

for (int i = 0; i < n; i++) {
int cItem = Integer.parseInt(st.nextToken());
p[i] = (int) mul(pw[i], cItem);
}

SegmentTree tree = new SegmentTree(p.length);
tree.construct(p);
for (int i = 0; i < q; i++) {

int op = Integer.parseInt(st.nextToken());
int l = Integer.parseInt(st.nextToken());
int r = Integer.parseInt(st.nextToken());
if (op == 1) {
tree.updateValue(p, l, (int) mul(pw[l], r));
} else {
long ans = tree.getSum(l, r);
bw.write( ans == 0 ? "Yes" : "No");
bw.write("\n");
}
}
} else {
int[] c = new int[n];

for (int i = 0; i < n; i++) {
int cItem = Integer.parseInt(st.nextToken());
c[i] = cItem;
}
for (int i = 0; i < q; i++) {
int op = Integer.parseInt(st.nextToken());
int l = Integer.parseInt(st.nextToken());
int r = Integer.parseInt(st.nextToken());
if (op == 1) {
c[l] = r;
} else {
long ans = c[l];
bw.write( ans == 0 ? "Yes" : "No");
bw.write("\n");
}
}
}

bw.close();
br.close();
}
}```

## Problem solution in C++ programming.

```#include <iostream>
#include <vector>
#include <cmath>
#include <ctime>
#include <cassert>
#include <cstdio>
#include <queue>
#include <set>
#include <map>
#include <fstream>
#include <cstdlib>
#include <string>
#include <cstring>
#include <algorithm>
#include <numeric>

#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define forn(i, n) for (int i = 0; i < (int)(n); ++i)
#define for1(i, n) for (int i = 1; i <= (int)(n); ++i)
#define ford(i, n) for (int i = (int)(n) - 1; i >= 0; --i)
#define fore(i, a, b) for (int i = (int)(a); i <= (int)(b); ++i)

using namespace std;

typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vpi;
typedef vector<vi> vvi;
typedef long long i64;
typedef vector<i64> vi64;
typedef vector<vi64> vvi64;

template<class T> bool uin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool uax(T &a, T b) { return a < b ? (a = b, true) : false; }

const int maxn = 110000;
const i64 P = 1000000000 + 7;

i64 deg(i64 x, i64 d) {
d %= P - 1;
if (d < 0) d += P - 1;
i64 y = 1;
while (d) {
if (d & 1) y *= x, y %= P;
x *= x, x %= P;
d /= 2;
}
return y;
}

i64 f[maxn], d[maxn], a[maxn];

void add(i64 &x, i64 y) {
x += y; x %= P;
}

void fadd(int i, i64 x) {
for (; i < maxn; i |= i + 1) add(f[i], x);
}

i64 fsum(int i) {
i64 s = 0;
for (; i >= 0; i &= i + 1, --i) add(s, f[i]);
return s;
}

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.precision(10);
cout << fixed;
#ifdef LOCAL_DEFINE
freopen("input.txt", "rt", stdin);
#endif

int n, q;
i64 A, B;
cin >> n >> A >> B >> q;
i64 z = -B * deg(A, -1) % P;
//    cerr << z << '\n';
d[0] = 1;
forn(i, n) {
cin >> a[i];
//        a[i] *= d[i]; a[i] %= P;
d[i + 1] = d[i] * z % P;
}
forn(i, n) fadd(i, a[i] * d[i]);
forn(i, q) {
int t;
cin >> t;
if (t == 1) {
int i;
i64 x;
cin >> i >> x;
//            --i;
fadd(i, (x - a[i]) * d[i]);
a[i] = x;
} else {
int l, r;
cin >> l >> r;
//            --l;
++r;
i64 res = fsum(r - 1) - fsum(l - 1);
res %= P;
if (!z) res = a[l];
//            cerr << res << '\n';
cout << (res ? "No" : "Yes") << '\n';
}
}

#ifdef LOCAL_DEFINE
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
return 0;
}```

## Problem solution in C programming.

```#include<stdio.h>
#define MAXN 100000
#define MOD 1000000007
int n, q, type, u, v;
long long a[MAXN+2], c1, c2, x, it[MAXN*4 + 2];
long long modPow(long long x, long long y)
{
long long res = 1;
while(y)
{
if( y & 1 )
{
res = res * x % MOD;
}
y >>= 1;
x = x * x % MOD;
}
return res;
}
void build(int node, int lef, int rig)
{
if( lef == rig )
{
it[node] = a[lef];
return;
}
int lnode = ( node << 1 );
int rnode = ( ( node << 1 ) | 1 );
int mid = ( ( lef + rig ) >> 1 );
build(lnode, lef, mid);
build(rnode, mid+1, rig);
int len = mid - lef + 1;
it[node] = ( it[lnode] + it[rnode] * modPow(x, len) ) % MOD;
}
void update(int node, int lef, int rig, int pos, long long val)
{
if( lef > pos || rig < pos )
{
return;
}
if( lef == rig )
{
it[node] = a[pos] = val;
return;
}
int lnode = ( node << 1 );
int rnode = ( ( node << 1 ) | 1 );
int mid = ( ( lef + rig ) >> 1 );
update(lnode, lef, mid, pos, val);
update(rnode, mid+1, rig, pos, val);
int len = mid - lef + 1;
it[node] = ( it[lnode] + it[rnode] * modPow(x, len) ) % MOD;
}
long long get(int node, int lef, int rig, int l, int r)
{
if( lef > r || rig < l )
{
return 0;
}
if( lef >= l && rig <= r )
{
return it[node] * modPow(x, lef - l) % MOD;
}
int lnode = ( node << 1 );
int rnode = ( ( node << 1 ) | 1 );
int mid = ( ( lef + rig ) >> 1 );
return ( get(lnode, lef, mid, l, r) + get(rnode, mid+1, rig, l, r) ) % MOD;
}
int main()
{
scanf("%d %lld %lld %d", &n, &c1, &c2, &q);
for( int i = 0 ; i < n ; ++i )
{
scanf("%lld", a + i);
}
x = ( MOD - c2 ) * modPow(c1, MOD - 2) % MOD;
build(1, 0, n-1);
while( q --> 0 )
{
scanf("%d", &type);
if( type == 1 )
{
scanf("%d %lld", &u, &c1);
update(1, 0, n-1, u, c1);
}
else
{
scanf("%d %d", &u, &v);
long long tmp = get(1, 0, n-1, u, v);
if( get(1, 0, n-1, u, v) == 0 )
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
}
return 0;
}```