AGARTHA IS REAL#12268

AGARTHA IS REAL (Editoryal)

Problem Author:

De3b0o

Prepared by:

De3b0o

Edited by:

Hasan Saleh (MathModel)

Solution

(We'll be referring to the current value of after all the operations as )

can't become negative at any time, because then both M-operations and S-operations make it go even further in the negatives so it won't ever reach . That means in order to make equal to , we first have to make it a multiple of (\text{cur}\mod z = 0) and then keep performing S-operations until it's .

Let's first deal with the cases. As we said earlier, can't be negative, so if is initially negative then the answer is .

The other case is if we can't make make a multiple of . It's enough to check the value (n \cdot x^z \cdot y^z)\mod z, if it's not then we can't make a multiple of .

Proof: Since there are only different cur\mod z values, multiplying by more than times will end us up in a cycle.

Now that we're done with the cases, we will always have an answer.

We can clearly see that in the optimal solution we won't ever do an M-operation unless \text{cur} < z is true, because if \text{cur} \ge z we can keep doing S-operations until \text{cur} < z, that's because \text{cur}\mod z = (\text{cur}-z)\mod z, and since not doing the S-operations before the M-operation will require us to do more S-operations in the future which is clearly not optimal.

Let's solve the case where x=y:

Claim: We won't do more than M-operations.

Proof: For to be a multiple of , must have all the prime factors of . When we do an M-operation we're adding prime factors to , and the maximum difference between the number of occurrences of a prime factor in and the number of occurrences of the same prime factor in is , so we won't need more than M-operations to make have all the prime factors of .

That means for x=y we can just keep doing M-operations while \text{cur} < z and if ever becomes larger than we can make equal to \text{cur}\mod z with a cost of \left \lfloor{\frac{\text{cur}}{z}} \right \rfloor (by repeatedly doing S-operations), We stop when \text{cur}=0.

Now to solve the full problem, Let's first define the state () as the state where we've multiplied times by and times by and must equal to (n \cdot x^i \cdot y^j)\mod z (we'll refer to the value of in this state as \text{cur}[i][j]).

We can use a dynamic programming approach:

\text{dp}[i][j] is equal to the minimum cost possible to reach the state ()

Base case:

\text{dp}[0][0] = \left \lfloor{\frac{n}{z}} \right \rfloor

Transition:

\text{dp}[i][j] = \min(\text{dp}[i-1][j] + \left \lfloor{\frac{\text{cur}[i-1][j] \cdot x}{z}} \right \rfloor , \text{dp}[i][j-1] + \left \lfloor{\frac{\text{cur}[i][j-1] \cdot y}{z}} \right \rfloor)

The answer is the minimum \text{dp}[i][j] value where \text{cur}[i][j] = 0.

Now since we won't make more than M-operations, the complexity for the dp is \mathcal{O}(z^2), which is way too large.

As we said in the x=y solution, We don't need more than M-operations to make a multiple of . That means we can always get an answer less than 10^{11}. Since the maximum answer we could get if we do the M-operations arbitrary is \log(z) \cdot \left \lfloor{\frac{\max(x,y) \cdot (z-1)}{z}}\right \rfloor + \log(z) \cdot (\log(z)+1) which is strictly less than 10^{11}.

Since the answer is always less than 10^{11}, We won't do more than 5\cdot10^5 M-operations because the cost for them alone would be larger than 10^{11}.

That optimizes the dp solution to \mathcal{O}(10^{11}) by making 5 \cdot 10^5 the limit for , but that's still too slow.

Let's observe the state () where both and are strictly larger than , it's guaranteed that \text{cur}[i-1][j]=\text{cur}[i][j-1]=0, and since \min(\text{dp}[i-1][j],\text{dp}[i][j-1]) \le \text{dp}[i][j], we don't care about the state () because we already have a better answer.

Now we can run the previous dp two times, the first time with i \le \log(z) , j \le 5 \cdot 10^5, and the second time with i \le 5 \cdot 10^5 , j \le \log(z).

So the total complexity of the code is \mathcal{O}(5 \cdot 10^5 \cdot \log(z)) which is fast enough to pass.


#include<bits/stdc++.h>
#define ll long long
#define d3 ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define cans cout << ans << "\n";
 
using namespace std;

const ll N = 500000 , lg = 35;

ll n , x , y , z , ans = LLONG_MAX;
ll dp[lg][N];
ll md[2][N];

ll fp(ll a , ll b)
{
    if(b==0)
        return 1;
    ll c = fp(a,b/2);
    if(b%2)
        return c*c%z*a%z;
    else
        return c*c%z;
}

ll Mcost(ll a)
{
    return a*(a+1)/2;
}

void rec(ll a , ll b)
{
    dp[0][0]=n/z;
    md[0][0]=md[1][0]=1;
    for(int i = 1 ; N>i ; i++)
    {
        md[0][i]=md[0][i-1]*a%z;
        md[1][i]=md[1][i-1]*b%z;
    }
    for(int i = 1 ; lg>i ; i++)
    {
        ll p = n*md[0][i-1]%z;
        p*=a;
        dp[i][0]=dp[i-1][0]+p/z;
    }
    for(int i = 1 ; N>i ; i++)
    {
        ll p = n*md[1][i-1]%z;
        p*=b;
        dp[0][i]=dp[0][i-1]+p/z;
    }
    for(int i = 1 ; lg>i ; i++)
    {
        for(int j = 1 ; N>j ; j++)
        {
            ll p = n*md[0][i-1]%z*md[1][j]%z;
            p*=a;
            dp[i][j]=dp[i-1][j]+p/z;
            p = n*md[0][i]%z*md[1][j-1]%z;
            p*=b;
            dp[i][j]=min(dp[i][j],dp[i][j-1]+p/z);
        }
    }
    for(int i = 0 ; lg>i ; i++)
    {
        for(int j = 0 ; N>j ; j++)
        {
            if(n*md[0][i]%z*md[1][j]%z==0)
                ans=min(ans,dp[i][j]+Mcost(i+j));
        }
    }
}

int main()
{
    d3
    cin >> n >> x >> y >> z;
    ll e = n*fp(x,100)%z*fp(y,100)%z;
    if(n<0||e!=0)
    {
        cout << -1;
        return 0;
    }
    rec(x,y);
    rec(y,x);
    cans
}