Parag Patkulkar
Parag Patkulkar

Reputation: 19

Problem with Modular Subtraction while solving a CP question

I am trying to solve this https://codeforces.com/problemset/problem/2035/D codeforces problem. I understand the logic and implementation, but I guess I am failing a modular arithmetic. Here is my code:

ll modAdd(ll a, ll b, ll mod) {
    return (a % mod + b % mod) % mod;
}

ll modSub(ll a, ll b, ll mod) {
    return ((a - b)%mod + mod) % mod; // Adding mod ensures non-negative result
}

// Function for modular multiplication
ll modMul(ll a, ll b, ll mod) {
    return (1LL * (a % mod) * (b % mod)) % mod; // 1LL ensures no overflow for large numbers
}

// Function for modular exponentiation
ll modExp(ll base, ll exp, ll mod) {
    ll result = 1;
    base = base % mod;
    while (exp > 0) {
        if (exp % 2 == 1) {
            result = modMul(result, base, mod);
        }
        base = modMul(base, base, mod);
        exp /= 2;
    }
    return result;
}

class Compare {
public:
    bool operator()(pair<ll, ll> below, pair<ll, ll> above)
    {
        return below.first > above.first;
    }
};

void solve() {
    ll n;
    cin>>n;

    vector<ll> v(n);
    for(ll i = 0; i<n; i++)cin>>v[i];

    priority_queue<pair<ll, ll>, vector<pair<ll,ll>>, Compare> pq;
    ll sum = 0;

    vector<ll> ans;
    for(ll i = 0; i<n; i++){
        
            ll sa = v[i];
            ll cnt = 0;

            while(sa % 2 == 0){
                sa = sa / 2;
                cnt++;
            }

            while(!pq.empty() && pq.top().first <= v[i]){
                
                
                ll val = pq.top().first;
                cnt+=pq.top().second;
                val = modMul(val, modExp(2, pq.top().second, MOD)-1, MOD);

                sum = modSub(sum, val, MOD);
                //sum = modAdd(pq.top().first, sum, MOD);

                for(ll j = 0; j<pq.top().second; j++){
                    v[i] = modMul(v[i], 2, MOD);
                }
                
                pq.pop();
            }
    
        
            sum =modAdd(v[i], sum, MOD);
            
            pq.push({sa , cnt});

    cout<<sum<<" ";    
    }

    cout<<endl;
}

Explanation:
Variable sa -> stripped 'a' is obtained by dividing the array element by 2 until it can't, such that it doesn't have factor 2.
Variable cnt -> number of times 'a' can be divided by 2

Kept a priority queue of these 2 as a pair.
Whenever an array element is greater than or equal to sa, I will multiply that element by 2^cnt, because doing this will increase the sum, by this way I am propogating the 2's power to the element that will give be largest sum when multiplied with.

Fails on test 3, I suspect that it is because of modular subtraction, but not sure what actually is causing the error.

Upvotes: -1

Views: 61

Answers (1)

Parag Patkulkar
Parag Patkulkar

Reputation: 19

Found what was wrong, it was just comparison in the while loop

while(!pq.empty() && **pq.top().first <= v[i]**)

Here, the value of v[i] can get smaller than first value of priority queue, because of using mod on v[i], to get the correct answer, I needed to compare that with complete value without modding it

Changed it to this

while(!pq.empty() && (cnt > 32 || pq.top().first <= sa*(1ll << cnt)))

And it worked, though priority queue gave a TLE.

Upvotes: 1

Related Questions