Overflow because n\le 10^{12}. Isn’t this O(n\log{n})? Or can you prove that the ranges of equal values allow you to solve it faster?
Since the sequence is non-increasing, all similar values should lie together in segments,
so complexity should be O(numberOfSegments), and we know the there can be atmost 2*sqrt(n) segments from here [Tutorial] Math note — Möbius inversion - Codeforces, I don’t know the exact proof.
Right… stupid mistake… It works btw.
Yes I realised you were correct. I didn’t realise that at any point, a value can be in at most 2 ranges(Prefix and suffix). But the actual complexity is O(\sqrt{n}\log{n})
take MODs in sum functions
it is leading to tle
MyExplanation:
If we know m is prime, then we can also use Fermats’s little theorem to find the inverse.
a and m are co-prime..
a^(m-1 )≅ 1 (mod m)
If we multiply both sides with a^(-1), we get :
a^(-1) ≅ a ^(m-2) (mod m)
For calculating the sum of divisors of all the no from 1 to n
We notice that i occurs n/i times in given range 1 to n.
for ( i = 1 to n)
ans += i*(n/i);
But , N = 10^12 so , it gives TLE for O(n) time complexity
So we have to optimize it..
We notice some consecutive no's l , ...., r have same value of n/i = n/r
So we have to take a fast sum of all such intervals and multipy it by n/i
since l , .. r is consecutive so it forms a A.P having difference 1 .
The Only thing we now need to do is to calculate r .
And r can be calculated using :
r = n/(n/l)
ans = 0
for l = 1 to n :
r = n/(n/l) // here we are going to rightmost side of current range..
let us consider some consecutive no's l , ...., r which all have same value for n/l = n/r
(summation of no from l to r *(n/l) ) == (( ( r - l + 1 )*( r + l ))/2)*(n/l) %mod
summation of no from l to r = (( r - l + 1 )*( r + l ))/2 %mod
summation of no from l to r = (( r - l + 1 )*( r + l ))*(2^-1) %mod
summation of no from l to r = (( r - l + 1 )*( r + l ))*binpow(2,mod-2,mod) %mod
binpow(2,mod-2,mod) = mod inverse of 2 . here 2^(-1) == 2^(mod-2) %mod , by fermat little's theorm..
ans += ( (( r - l + 1 )*( r + l )) * binpow(2,mod-2,mod) ) % mod
l = r+1 // here we are going to leftmost value no of next range..
My Code:
long long binpow(long long a, long long b, long long m) {
a %= m;
long long res = 1;
while (b > 0) {
if (b & 1)
res = res * a % m;
a = a * a % m;
b >>= 1;
}
return res;
}
void solution(){
ll n ;
cin >> n ;
ll ans = 0 ;
for( ll l = 1 ; l <= n ; ){
ll r = n/(n/l);
ans =( ans +(((((( ( r - l + 1 )%mod)*(( r + l )%mod))%mod)*binpow(2,mod-2,mod))%mod)*(n/l))%mod)%mod;
l = r+1;
}
cout<<ans<<"\n";
return;
}
int main()
{
// freopen( "input.txt" , "r" , stdin );
// freopen( "output.txt" , "w" , stdout );
amarks444;
// ll t;
// cin>>t;
// while(t--)
solution();
return 0;
}
the question is not to calculate it for n ; if it was for n upto sqrt n i +n/i etc etc would have been better but i think
initialize sum=0;
for(int i=1;i<=n;i++)
{
sum+=(n/i)*i; (or n-(n%i)) would be better
}
and than cout<<sum%A;
this approach works because no. of integers between 1 to n that are divisible by i are n/i;
long long sumOfDivisors(int N)
{
long long left = 1, sum = 0;
while(left <= N)
{
long long val = N/left;
long long right = N/val;
sum+=(((right*(right+1))/2)-((left*(left-1))/2))*val;
left= right+1;
}
return sum;
}