how to Calculate this series - c++

#include <iostream>
#include <math.h>
using namespace std;
int fact(int number)
{
unsigned long long int p = 1;
if (number == 0) {
return p;
}
for (int i = 1; number >= i; i++) {
p = p * i;
}
return p;
}
int main()
{
long long int a, x, sum = 0, result;
int n ;
cin >> a;
cin >> x;
cin >> n;
for (int k = 0; n >= k; k++) {
result = fact(n) / (fact(k) * fact(n - k));
sum = sum + (result * pow(x, k) * pow(a, n - k));
}
cout << sum;
return 0;
}
I want to calculate this series
So I considered the long long int sum, but the sum number sometimes gets too big. What can I do to save the sum number without using library?

First of all I would suggest to use binomial theorem -- what you are computing is just pow(x+a, n)
If you want to do this through series, do not compute the binomial coefficient using factorials but something like this
int bin_coeff(int n, int k){
int lim = k > n/2 ? k : n - k;
int sum = 1;
for (int i = n; i > lim; i--){
sum *= i;
}
for (int i = 2; i < (n - lim + 1); i++){
sum /= i;
}
return sum;
}

Related

Can I optimize segmented Sieve of Eratosthenes

I am trying to find the number of primes in a given range in c++. But it still shows TLE. Can I optimize it further?
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T;
std::cin>>T;
while(T--){
int r,Y;
cin >> r>>Y;
int count=0;
int l=1;
vector<bool>isPrime(r - l + 1,true); //filled by true
for (long long i = 2; i * i <= r; ++i) {
for (long long j = max(i * i, (l + (i - 1)) / i * i); j <= r; j += i) {
if(isPrime[j - l]){
isPrime[j - l] = false;
count++;
}
}
}
count=isPrime.size()-count-1;
std::cout<<count<<"\n";
}
return 0;
}

Can't find a range of maximum product subarray

I'm solving Maximum Product Subarray problem on C++. My code finds only a max.product of subarray, but not a range.
I found some explanation here - https://www.geeksforgeeks.org/maximum-product-subarray/ and used the code. How could I find the range(Left index, Right index) of subarray that gives me maximum product? (I found some similar posts here, but all of them on java, and i can't understand them properly)
#include<bits/stdc++.h>
#include <stdio.h>
using namespace std;
int min(int x, int y) {
return (x < y) ? x : y;
}
int max(int x, int y) {
return (x > y) ? x : y;
}
int solve(int a[], int n){
int maxend = 0, minend = 0;
int maxans = 0;
for (int i = 1; i <= n; i++){
int temp = maxend;
maxend = max(a[i], max(a[i] * maxend, a[i] * minend));
minend = min(a[i], min(a[i] * temp, a[i] * minend));
maxans = max(maxans, maxend);
}
return maxans;
}
int main(void){
int n, a[10000];
cin >> n;
for(int i=1; i<=n; i++){
cin >> a[i];
}
cout << solve(a, n);
return 0;
}
If all you need is the range information, you can keep track of the indices where maxans variable changed. That would indicate to you where the maximum product comes from, which would be the right endpoint of the range. Then, after you compute the maxans, you can basically go left until you get the maximum product, at which point you will have found the left interval.
The following implementation can serve as a demonstration.
int solve(int a[], int n){
int maxend = 0, minend = 0;
int maxans = 0;
int max_r = -1;
for (int i = 1; i <= n; i++){
int temp = maxend;
maxend = max(a[i], max(a[i] * maxend, a[i] * minend));
minend = min(a[i], min(a[i] * temp, a[i] * minend));
if(maxans < maxend){
maxans = maxend;
max_r = i;
}
}
int max_l = max_r;
for(int i=1; i < maxans; max_l--){
i = i * a[max_l];
}
//At this point you have the range [max_l, max_r] that yield maxans as the product
return maxans;
}

Euler's totient function practice code fails in online judge

This is specifically UVA problem number 11327:
Given a series of all rational numbers between 0 and 1 (0/1, 1/1, 1/2, 1/3, 2/3,..., n/d) print the k-th fraction
I've used their debugger and my program outputs the exact same answers they give but the judge still marks it as incorrect.
I'm using Euler's totient function to find the denominator and iterating through GCDs that equal 1 to find the numerator. As far as I could find online, this should suffice.
Any help would be appreciated.
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <math.h>
using namespace std;
//Calculate the greatest common divisor of a and b
long long GCD(long long a, long long b){
if (a == 0){
return b;
}
return GCD(b%a, a);
}
int main(){
long long input;
vector <long long> inputVector;
vector <long long> phiValues;
long long totient;
long long total;
int numerator;
int denominator;
while(cin >> input){
if(input == 0){
break;
}
inputVector.push_back(input);
}
// Calculate phi for all integers from 1 to
// 20000 and store them
for(int i = 1; i <= 200000; i++){
long long current = i;
totient = current;
for(long long k = 2; k <= sqrt(i); k++){
if(current % k == 0){
totient -= totient / k;
while(current % k == 0){
current /= k;
}
}
}
if(current > 1){
totient -= totient / current;
}
phiValues.push_back(totient);
}
for(int i = 0; i < inputVector.size(); i++){
long long N = inputVector[i];
total = 1;
for(int j = 0; j <= phiValues.size(); j++){
if(total >= N){
if(N == 1){ //For the case of N = 1
denominator = 1;
}else{
denominator = j;
}
total -= phiValues[j-1];
break;
}
total += phiValues[j];
}
int index = 0;
for(int j = 1; j <= denominator; j++){
if(GCD(j, denominator) == 1){
index++;
if(index == N - total){
numerator = j;
break;
}
}
}
cout << numerator << '/' << denominator << endl;
}
return 0;
}
Here #jte states that calculation of PHI can be achieved in O(N*logN):
phi[0] = phi[1] = 0;
for (int i=2; i<maxn; ++i)
phi[i] = i - 1;
for (int i=1; i<maxn; ++i)
for (int j=i+i; j<maxn; j+=i)
phi[j] -= phi[i];
I could not find problem of your code. May be it is TLE (time limit exceeded) problem, because you should use binary search to find denominator. But this code will get ACCEPTED:
#include<bits/stdc++.h>
using namespace std;
const int N = 200031;
int pr[N+31],phi[N+31];
vector<int> P[N+31];
long long S[N+31];
int count(int n,int X)
{
int res=n;
int N=P[X].size();
for (int mask=1;mask<(1<<N);mask++) {
int C=0;
int prod=1;
for (int j=0;j<N;j++)
if (mask&(1<<j))
C++,
prod*=P[X][j];
if (C%2)
res-=n/prod;
else
res+=n/prod;
}
return res;
}
int solve(int need,int val)
{
int l,r;
l=1;
r=val;
while (l<r) {
int mid=l+r;
mid/=2;
int Q=count(mid,val);
if (Q>=need)
r=mid;
else
l=mid+1;
}
return l;
}
int main()
{
ios_base::sync_with_stdio(0);
pr[1]=1;
for (int i=1;i<=N;i++) {
if (pr[i])
continue;
for (int j=i;j<=N;j+=i)
P[j].push_back(i),
pr[j]=1;
}
for (int i=1;i<=N;i++) {
phi[i]=i;
for (int j=0;j<P[i].size();j++) {
int val=P[i][j];
phi[i]=phi[i]/val*(val-1);
}
}
for (int i=1;i<=N;i++)
S[i]=S[i-1]+phi[i];
long long x;
while (cin>>x) {
if (x==0)
break;
--x;
if (x==0)
{
cout<<0<<"/"<<1<<endl;
continue;
}
int id=lower_bound(S+1,S+N+1,x)-S;
x-=S[id-1];
int ps=solve(x,id);
cout<<ps<<"/"<<id<<endl;
}
return 0;
}

Divide and Conquer algorithm in C++

There is this one problem in some online judge that I have no clue on how to get accepted.
The problem goes like this first line contained two number
N (0 < N < 2^18)
M (0 < M < 2^20)
The second line contained N numbers
ai (0 < ai < 2^40)
The question is how many X are there that satisfied:
M = floor(X/a1) + floor(X/a2) + ... + floor(X/an)
My naive solution:
#include<bits/stdc++.h>
using namespace std;
long long n,m,i,j,haha,sum;
int main()
{
cin >> n >> m;
haha = 0;
long long ar[n+5];
for(i = 0; i < n; i++) cin >> ar[i];
sort(ar,ar+n);
for(i = ar[0]+1; i < m*ar[0]; i++){
sum = 0;
for (j = 0; j < n; j++) sum += i/ar[j];
if (sum == m) haha += 1;
else if (sum >= m) break;
}
cout << haha << endl;
}
Update1:
My binary search solution (still didn't pass the time limit):
#include<bits/stdc++.h>
using namespace std;
long long n,m,i,l,r,mid,ans,tmp,cnt,haha;
long long ar[2621440];
long long func(long long x){
haha = 0;
for (i = 0; i < n; i++) haha += x/ar[i];
return haha;
}
int main()
{
cin >> n >> m;
for(i = 0; i < n; i++) cin >> ar[i];
sort(ar,ar+n);
l = ar[0];
r = ar[0]*m;
mid = (l+r)/2;
tmp = func(mid);
while (tmp != m){
mid = (l+r)/2;
tmp = func(mid);
if (l == r) break;
if (tmp < m) l = mid+1;
else if (tmp > m) r = mid-1;
else break;
}
ans = 0;
if (tmp == m) ans += 1;
cnt = mid;
while (func(cnt-1) == m){
ans += 1;
cnt -= 1;
}
cnt = mid;
while (func(cnt+1) == m){
ans += 1;
cnt += 1;
}
cout << ans << endl;
}
Update
Going with the binary search approach, here is my new code:
// compute X/ai sum
long long summarize(long long ar[], long long n, long long X)
{
long long sum = 0;
for (long long i = 0; i < n; i++)
{
sum += X/ar[i];
}
return sum;
}
bool get_range(long long ar[], int n, int m, pair<long long, long long>& range)
{
long long sum = 0;
long long x;
// reduce range
while (range.first < range.second)
{
x = (range.first + range.second) / 2;
sum = summarize(ar, n, x);
if (sum < m)
{
range.first = x + 1;
}
else if (sum > m)
{
range.second = x;
}
else if (x == range.first)
{
return true; // single element
}
else
{
break;
}
}
if (sum != m)
{
return false;
}
// check surroundings for lower / upper bound.
sum = summarize(ar, n, range.first);
if (sum != m)
{
auto r1 = make_pair(range.first + 1, x);
if (get_range(ar, n, m, r1))
{
range.first = r1.first;
}
else
{
range.first = x;
}
}
sum = summarize(ar, n, range.second - 1);
if (sum != m)
{
auto r2 = make_pair(x + 1, range.second - 1);
if (get_range(ar, n, m, r2))
{
range.second = r2.second;
}
else
{
range.second = x + 1;
}
}
return true;
}
int main()
{
int n, m;
cin >> n >> m;
long long *ar = new long long[n];
long long ar_min = LLONG_MAX;
for(long long i = 0; i < n; i++)
{
cin >> ar[i];
ar_min = min(ar[i], ar_min);
}
// initial range of possible X values
auto range = make_pair(m / (ar_min * n), m * ar_min);
if (get_range(ar, n, m, range))
{
cout << (range.second - range.first) << endl;
}
else
{
cout << 0 << endl;
}
}
Core functionality is the get_range function, which takes a possible range ([range.first, range.second), so second is not part of the range) and reduces the range so all elements in range satisfy the condition. It is first iteratively adjusting range bounds until the middle of the range is part of the result or until it's clear that there is no result in range. Then, if there is any result, it is recursively checking the sub-ranges below and above the found result in order to retrieve the bounds of the whole result range.
Version 1
You are only dealing with positive numbers greater than zero.
M = floor(X/a1) + floor(X/a2) + ... + floor(X/an)
For every sub-term floor(X/a1), there is floor(X1/ai) <= floor(X2/ai) if X1 < X2. So the only possible X values resulting in M are those, where floor(X1/ai) == floor(X2/ai) for all i (or all ai).
For each ai this is exactly the Range of X1=k*ai until X2=k*ai+(ai-1) for some k.
This means, if any solution exists, the range of X values will be between k*min(ai) and (k+1)*min(ai) for some 0 < k <= m.
So it might be worth to first get the range of possible results and then check the individual values only within the range.
Resulting algorithm:
// compute X/ai sum
long long summarize(long long ar[], long long n, long long X)
{
long long sum = 0;
for (long long i = 0; i < n; i++)
{
sum += X/ar[i];
}
return sum;
}
int main()
{
int n, m;
cin >> n >> m;
long long *ar = new long long[n];
long long ar_min = LLONG_MAX;
for(long long i = 0; i < n; i++)
{
cin >> ar[i];
ar_min = min(ar[i], ar_min);
}
// lowest possible k
long long k = m / (ar_min * n);
// get the value k for a possible range of X values
for (; k <= m; k++)
{
auto x = ar_min * (k + 1);
long long sum = summarize(ar, n, x);
if (sum > m)
{
break;
}
}
long long X_min = k * ar_min, X_max = (k + 1) * ar_min;
long long result = 0;
// count possible X values
for (long long x = X_min; x < X_max; x++)
{
long long sum = summarize(ar, n, x);
if (sum == m)
{
++result;
}
else if (sum > m)
{
break;
}
}
cout << result << endl;
}
It got a bit more complicated than I first expected. I hope it's still some sort of improvement.
I believe that the expected solution for this is binary search.
Define f(x) = sum_i f(x/a_i). Without loss of generality, assume that a_i are given in inceasing order.
Clearly,
f(0) = 0 < M
f(M*a_1) ≥ M
f(x) ≥ f(y) if x≥y
Thus you can do binary search to find the lowest value of x such that f(x) = M, with start = 0 and end = M*a_1 as the initial limits for the binary search.
To find the upper limit for x, do another binary search or just loop through all values in the array to find the smallest y such that floor(y/ai) > floor(x/ai) for some i.
Got accepted (finally) using two binary search (each for lower bound, and upper bound) with this code:
#include<bits/stdc++.h>
using namespace std;
long long n,m,i,l,r,mid1,mid2,ans,tmp,cnt,haha,k;
long long ar[26214400];
long long func(long long x){
haha = 0;
for (k = 0; k < n; k++) haha += x/ar[k];
return haha;
}
int main()
{
cin >> n >> m;
for(i = 0; i < n; i++) cin >> ar[i];
sort(ar,ar+n);
l = ar[0];
r = ar[0]*m;
mid1 = (l+r)/2;
tmp = func(mid1);
while (l < r){
mid1 = (l+r)/2;
tmp = func(mid1);
if (tmp < m) l = mid1+1;
else if (tmp > m) r = mid1-1;
else r = mid1-1;
}
mid1 = l; //lower bound
l = ar[0];
r = ar[0]*m;
mid2 = (l+r)/2;
tmp = func(mid2);
while (l < r){
mid2 = (l+r)/2;
tmp = func(mid2);
if (tmp < m) l = mid2+1;
else if (tmp > m) r = mid2-1;
else l = mid2+1;
}
mid2 = r; //upper bound
while (mid1 <= mid2 and func(mid1) != m) mid1 += 1;
while (mid2 >= mid1 and func(mid2) != m) mid2 -= 1;
ans = mid2-mid1+1;
cout << ans << endl;
}

Count numbers in range divisible by K with a sum of digits in range

I have such a task:
Let's call a number "lucky" if it is divisible by K and sum of its digits lays in [P, Q]. Count the quantity of "lucky" numbers in [A, B].
1 ≤ A, B < 10^11,
1 ≤ P, Q ≤ 99,
1 ≤ K ≤ 10^11.
Time for each test - 5 seconds
Here is my code
#include <iostream>
#include <fstream>
using namespace std;
int sum;
long long k;
int number[10];
int digits[10];
int p;
int q;
long long a;
long long b;
int delta;
bool flag = false;
long long memory[100000][100][10][2];
long long pow (int a, int b)
{
long long res = 1;
for(int i = 0; i < b; i++)
res *= a;
return res;
}
int sumOfDigits(long long number)
{
int sum = 0;
while(number != 0)
{
sum += number % 10;
number /= 10;
}
return sum;
}
long long toLong(int digits[], int n)
{
long long sum = 0;
for(int i = 0; i < n; i++)
{
sum *= 10;
sum += digits[i];
}
return sum;
}
long long function(long long remainder// the remainder of division by k,
int currSum // current sum of digits,
int n //number of digit to be added,
bool allDigitsAllowed //says if all digits can be added to number)
{
if(n == 10)
{
int counter = 0;
for(int i = p; i <= q; i++)
{
long long res = i - currSum + remainder;
if(res%k == 0 && (allDigitsAllowed || i-currSum <= number[9]))
{
counter++;
if(!allDigitsAllowed && number[9] == i-currSum)
flag = true;
}
}
return counter;
}
long long res = 0;
int temp = 0;
while(currSum + temp <= q)
{
long long tempRemainder = (temp*pow(10,10-n)+remainder)%k;
if(temp == number[n-1] && !allDigitsAllowed)
{
if(tempRemainder < 100000)
{
if(memory[tempRemainder][currSum+temp][n+1][false] == -1)
memory[tempRemainder][currSum+temp][n+1][false] = function(tempRemainder, currSum + temp, n+1,false);
res += memory[tempRemainder][currSum+temp][n+1][false];
}
else
res += function(tempRemainder, currSum + temp, n+1,false);
//res += function(tempRemainder, currSum + temp, n+1,false);
break;
}
else
{
if(tempRemainder < 100000)
{
if(memory[tempRemainder][currSum+temp][n+1][true] == -1)
memory[tempRemainder][currSum+temp][n+1][true] = function(tempRemainder, currSum + temp, n+1,true);
res += memory[tempRemainder][currSum+temp][n+1][true];
}
else
res += function(tempRemainder, currSum + temp, n+1,true);
}
temp++;
}
return res;
}
long long F (long long a)
{
flag = false;
memset(&number, 0, sizeof(number));
sum = 0;
int i = 9;
while(a != 0)
{
number[i] = a%10;
a /= 10;
i--;
}
for(int j = 0; j < 10; j++)
swap(number[j],number[9-j]);
return function(0,0,1,false);
}
int main()
{
ifstream in("lucky.in");
ofstream out("lucky.out");
in >> k >> p >> q >> a >> b;
sum = p;
memset(&memory, -1, sizeof(memory));
long long result = - F(a) + flag;
memset(&memory, -1, sizeof(memory));
out<< result + F(b) << endl;
return 0;
}
In this solution I try to make a number with a determined sum of digits, adding digits one by one.
The problem is that I can't memorize all the the remainders of the division by k.
So how can I deal with this problem?
I would use something like:
unsigned int compute_number_sum(uint64_t n)
{
unsigned int res = 0;
while (n != 0) {
const uint64_t nd = n / 10;
res += static_cast<unsigned int>(n - 10 * nd); // equivalent to res += n % 10
n = nd;
}
return res;
}
uint64_t count_lucky_number(uint64_t A, uint64_t B, uint64_t K,
unsigned int P, unsigned int Q)
{
uint64_t res = 0;
const uint64_t min_i = (A + K - 1) / K * K;
for (uint64_t i = min_i; i <= B; i += K) {
const unsigned int numberSum = compute_number_sum(i);
res += P <= numberSum && numberSum <= Q;
}
return res;
}