Sunday, 19 April 2020

Atcoder Beginner Contest - 163

D - Sum of Large Numbers

Problem Statement : here


Solution - 
The tricky part is the addition of 10^100. So, let us assume that we are using k numbers to generate our sum. Clearly, in this case, the coefficient of 10^100 will be k. If we would have used k+1 terms, the coefficient would have differed and this makes the two numbers different. So the cases like 1+ 8 = 3+5+1 are not possible, because each of them has different coefficients of 10^100. So, what we are left with? 
Given k -> number of terms, what are the possible values of the sum I can get? 
So, if I calculate the minimum possible sum and the maximum possible sum, then I claim that we can get any number in between this sum range. It is a well-known fact. So, we use it in order to solve this question. The proof - intuitive that can be taken to convince is :
min-sum  = 0 + 1 + 2 + 3 .......... + k-1
max-sum = n-(k-1) + n-(k-2) + n-(k-3) + ....... + n
To get any sum in this range, we can start distributing the difference between given value and min-sum to 0 (until it becomes n-(k-1)), remaining to 1 and so on up to k-1 (until it becomes n).
The code : 
ll modp(ll a, ll b){ ll res = 1; while(b>0){ if (b&1) res = (res*a)%M1; a = (a*a)%M1; b>>=1; } return res; } ll minsum[200005]; void solve() { ll n,k; cin>>n>>k; minsum[1] = 0; ll maxsum = (((n*(n+1))%M1)*modp(2,M1-2))%M1; rep(i,2,n+2){ minsum[i] = (minsum[i-1] + i-1 + M1)%M1; } ll ans = 0; rep(i,k,n+2){ ans = (ans + maxsum - minsum[n-i + 1] - minsum[i] + 1 + M1)%M1; } cout << ans << endl; }