Editorial for Problem D2

Goku's Power

Author : shailesh_2004

Required Knowledge : DP, Math, Modulo Arithmetic

Time Complexity : O(Nlog2N)O(N \cdot log_2N)

Editorialist : shailesh_2004

Approach:

The value of nn depends on the value of n1n-1. The time complexity will be Nlog2NNlog_2N for each nn if we calculate the given expression. If we do this for TT cases then it will become TNlog2NT \cdot Nlog_2N which gives us TLE. Thus, we should precompute all values from 11 to 10510^5.

Let rep[n]rep[n] represent the number nn repeating nn times.

Let's divide the value for nn into three parts:

value[n]=rep[n]+value[n1]+rep[n]value[n] = rep[n] + value[n-1] + rep[n]

(This is not addition, it's concatenation)

To do this concatenation we need number of digits in the value of n1n-1. Let's store each value's size in another array (where size[i]size[i] represents number of digits in value[i]value[i]). Let dd be number of digits in the number nn.

First let's calculate rep[n]rep[n].

To find pattern, first observe any single digit number, let's say 55:

55555=5104+5103+5102+5101+510055555 = 5 \cdot 10^4 + 5 \cdot 10^3 + 5 \cdot 10^2 + 5 \cdot 10^1 + 5 \cdot 10^0

Now observe for multiple digits, let's say 1212:

12...12=1210112+1210102+.....+121012+12100212...12 = 12 \cdot 10^{11 \cdot 2} + 12 \cdot 10^{10 \cdot 2}  + ..... + 12 \cdot 10^{1 \cdot 2} + 12 \cdot 10^{0 \cdot 2}

Generalization for multiple digits:

n...n=n10(n1)d+n10(n2)d+.....+n101d+n100dn...n = n \cdot 10^{(n-1) \cdot d} + n \cdot 10^{(n-2) \cdot d}  + ..... + n \cdot 10^{1 \cdot d} + n \cdot 10^{0 \cdot d}

Take nn common, remaining part is in geometric progression with initial value as 11 and ratio as 10d10^d and there are n terms.

By using sum of GP formula which is:

a+ar+ar2+...+arn1=a(rn1)r1a + ar + ar^2 + ... + ar^{n-1} = \frac {a \cdot (r^n-1)} {r-1}

We can compute rep[n]rep[n] as follows:

rep[n]=n(10dn1)(10d1)rep[n] = \frac {n \cdot (10^{d \cdot n} - 1)} {(10^d - 1)}

(Use Modular Inverse)

Let srep[i]srep[i] represent size of rep[i]rep[i].

It's obvious that srep[i]=idsrep[i] = i \cdot d

size[i]=srep[i]+size[i1]+srep[i]size[i] = srep[i] + size[i-1] + srep[i]

Now, let's evaluate the answer by concatention:

value[n]=rep[n]+value[n1]+rep[n]value[n] = rep[n] + value[n-1] + rep[n]

(This is not addition, it's concatenation)

First let's concatenate second part to first part:

We need to append size[n1]size[n-1] zeroes to rep[n]rep[n] and add value[n1]value[n-1]. As size[n1]size[n-1] is large use binary exponentiation and modulo.

value[n]=rep[n]10size[n1]+value[n1]value[n] = rep[n] * 10^{size[n-1]} + value[n-1]

Then let's concatenate third part to current value[n]value[n]

We need to append srep[n]srep[n] zeroes and add n to it.

value[n]=value[n]10srep[n]+rep[n]value[n] = value[n] * 10^{srep[n]} + rep[n]

Time complexity is O(Nlog2N)O(N \cdot log_2N), here log2Nlog_2N factor is because of binary exponentiation and modular inverse.

Setter's Code:

// Author : Shailesh
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define vll vector<ll>
#define pb push_back
#define mp make_pair
#define endl "\n"
#define mod 1000000007
#define tot(a) a.begin(),a.end()
#define minii *min_element
#define maxii *max_element

ll binexp(ll a,ll b,ll mod2=mod)
{
    ll res=1;
    a%=mod2;
    while(b)
    {
        if(b%2)res=(res*a)%mod2;
        a=(a*a)%mod2;
        b>>=1;
    }
    return res;
}

ll modular_inverse(ll a,ll mod2=mod)
{
    // By Fermat's little theorem
    return binexp(a,mod2-2,mod2);
}

ll ans[100001];
void precompute()
{
    ans[1]=1;
    ll sz[100001];
    sz[1]=1;
    ll i;
    ll tens[6]={10,100,1000,10000,100000};
    ll j=0;
    ll d=1;
    for(i=2;i<=100000;i++)
    {
        if(i==tens[j])
        {
            j++;
            d++;
        }
        sz[i]=i*d+sz[i-1]+i*d;
        ll val=((i*(binexp(10,d*i)-1))%mod * modular_inverse(binexp(10,d) - 1))%mod;
        ans[i]=(((((val*binexp(10,sz[i-1]))%mod + ans[i-1])%mod)*binexp(10,i*d))%mod + val)%mod;
    }
}

void solve()
{
    ll n;
    cin>>n;
    cout<<ans[n]<<endl;
}

int main()
{
    ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
    precompute();
    ll t;cin>>t;while(t--)
    solve();
    return 0;
}

Tester's Code:

// Author : Naveen

// Program Start
// Libraries and Namespace Start
#include <bits/stdc++.h>
using namespace std;
// Libraries and Namespace End

//----------------------------------------------------------------

// Important Shortcuts Start
// Macros Start
#define F first
#define S second
#define pb push_back
#define all(v) v.begin(), v.end()
// Macros End

// Declarations Start
typedef long long int ll;
typedef vector<ll> vll;
// Declarations End

// Constants Start
const ll mod1 = 1e9 + 7;
const char newl = '\n';
// Constants End

// Binary Exponentiation Start
ll power(ll b, ll p, const ll mod) {
    if (b <= 0 || p < 0) {
        throw invalid_argument("The numbers can't be negative.");
    }
    ll res = 1;
    b %= mod;
    while (p > 0) {
        if (p & 1) {
            res = res * b % mod;
        }
        b = b * b % mod;
        p >>= 1;
    }
    return res;
}
// Binary Exponentiation End

// Modular Arithmetic Start
// Modular Inverse Function Start
inline ll mod_inv(ll n, const ll mod = mod1) {
    if (n < 0) {
        throw invalid_argument("The number can't be negative.");
    }
    return power(n, mod - 2, mod);
}
// Modular Inverse Function End
// Modular Arithmetic End


//----------------------------------------------------------------

// Solution Class Start
class Solution {
public:
    vll ans;

    Solution() {
        ans.assign(1e5 + 1, 0);
        ans[1] = 1;
        ll cou = 1;
        ll d = 1;
        for (ll i = 2;i <= ans.size();i++) {
            switch (i) {
                case 10:
                case 100:
                case 1000:
                case 10000:
                case 100000:
                    d++;
            }
            ll p = power(10, i * d, mod1);
            ans[i] = (ans[i - 1] * p) % mod1;
            cou += i * d;
            p = power(10, i * d, mod1);
            ll val = ((((p + mod1 - 1) % mod1) * (mod_inv((power(10, d, mod1) + mod1 - 1) % mod1, mod1))) % mod1 * i) % mod1;
            ans[i] = ((val * power(10, cou, mod1)) % mod1 + (ans[i] + val) % mod1) % mod1;
            cou += i * d;
        }
    }

    void solve(ll index) {
        //----------------------------------------------------------------

        ll n, i, j, k;
        cin >> n;
        cout << ans[n] << newl;

        // cout << "Case #" << index << ": " << ans << newl;

        //----------------------------------------------------------------
    }

    bool test_cases = true;
};
// Solution Class End

// Main Function Start
int main() {
    Solution sol;
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    ll test_cases = 1;
    if (sol.test_cases) {
        cin >> test_cases;
    }
    for (ll test_case = 1; test_case <= test_cases; ++test_case) {
        sol.solve(test_case);
    }
    return 0;
}
// Main Function End
// Program End
//----------------------------------------------------------------