Euler's totient function practice code fails in online judge - c++

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;
}

Related

how to find the biggest multiplication between numbers in a given array(limit is 100000 numbers)

I am trying to learn programming and in our school we have exercises which are automatically checked by a bot. The time limit is 1 second and the memory limit is 1024 mb.
I've tried sorting the array in an ascending order and then multiplicating the 2 highest numbers but that was too slow(my sorting algorithm could be slow so if possible suggest a sorting algorithm.)
This is the fastest way that I've been able to do:
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
int Maksimumas(int n, int X[]);
ofstream fr("U1rez.txt");
ifstream fd("U1.txt");
int main()
{
int n, A[100000], B[100000], maxi=0;
fd >> n;
for (int i = 0; i < n; i++) {
fd >> A[i];
}
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
B[j] = A[i] * A[j];
}
maxi = Maksimumas(n, B);
A[i] = B[maxi];
}
maxi = Maksimumas(n, A);
fr << A[maxi];
fr.close();
return 0;
}
int Maksimumas(int n, int X[])
{
int maxi = 0;
for (int i = 0; i < n; i++) {
if (X[maxi] < X[i]) {
maxi = i;
}
}
return maxi;
}
n is the size of the array for anyone wondering.
You don't need to sort the entire array - you just need the two largest positive numbers and the two smallest negative numbers. Everything in between is inconsequential.
Instead, you can go over all the input and keep track of the two largest positive numbers and two smallest negative numbers.; At the end of the iteration, multiply each pair (if found), and compare the results.
// fd is opened like the original question, n is the number of elements to read
// that part is omitted for brevity
int max = -1;
int preMax = -1;
int min = 1;
int preMin = 1;
int temp;
for (int i = 0; i < n; i++) {
fd >> temp;
if (temp > preMax) {
if (temp > max) {
preMax = max;
max = temp;
} else {
preMax = temp;
}
} else if (temp < preMin) {
if (temp < min) {
preMin = min;
min = temp;
} else {
preMin = temp;
}
}
}
int result = -1;
if (preMax >= 0) {
result = preMax * max;
}
if (preMin <= 0) {
int tempResult = preMin * min;
if (tempResult > result) {
result = tempResult;
}
}
return result;

prime seive algorithm giving a runtime error

I am trying to implement the Sieve of Eratosthenes algorithm but it giving a runtime error.
didn't get any output though. after providing the input,
#include<iostream>
using namespace std;
//Sieve Approach - Generate an array containing prime Numbers
void prime_sieve(int *p) {
//first mark all odd number's prime
for (int i = 3; i <= 10000; i += 2) {
p[i] = 1;
}
// Sieve
for (long long int i = 3; i <= 10000; i += 2) {
//if the current number is not marked (it is prime)
if (p[i] == 1) {
//mark all the multiples of i as not prime
for (long long int j = i * i; j <= 10000; j = j + i ) {
p[j] = 0;
}
}
}
//special case
p[2] = 1;
p[1] = p[0] = 0;
}
int main() {
int n;
cin >> n;
int p[10000] = {0};
prime_sieve(p);
//lets print primes upto range n
for (int i = 0; i <= n; i++) {
if (p[i] == 1) {
cout << i << " ";
}
}
return 0;
}
compiler didn't throwing any error also it is not providing the output also
program freezes for some seconds and then terminates
As mentioned in the comments, you are going out of bound.
There is also some confusion about the meaning of p[].
In addition, you are not using the value of n in the function, which leads to unnecessary calculations.
Here is a tested programme (up to n = 10000):
#include <iostream>
#include <vector>
#include <cmath>
//Sieve Approach - Generate an array containing prime Numbers less than n
void prime_sieve(std::vector<int> &p, long long int n) {
//first mark all odd number's prime
for (long long int i = 4; i <= n; i += 2) {
p[i] = 0;
}
// Sieve
for (long long int i = 3; i <= sqrt(n); i += 2) {
//if the current number is not marked (it is prime)
if (p[i] == 1) {
//mark all the multiples of i as not prime
for (long long int j = i * i; j <= n; j = j + i ) {
p[j] = 0;
}
}
}
//special cases
p[1] = p[0] = 0;
}
int main() {
long long int n;
std::cout << "Enter n: ";
std::cin >> n;
std::vector<int> p (n+1, 1);
prime_sieve(p, n);
//lets print primes upto range n
for (long long int i = 0; i <= n; i++) {
if (p[i] == 1) {
std::cout << i << " ";
}
}
return 0;
}

How do I resolve sigabrt error on codechef ide

Sigabrt runtime error occurs of a fatal error, because of an assert statement not returning true? Or use of excessive memory, I'm not able to figure out what I'm doing wrong here, help me out?
( problem 1343 C on codeforces) link
so here's the code.
#include <iostream>
#include <stdlib.h>
#include<vector>
using namespace std;
int check(int i,vector<int> a) {
if (a[i] > 0) {
return 1;
}
else return 0;
}
int main() {
int t;
cin >> t;
while (t--)
{
long int n;
cin >> n;
vector<int> a(n), b;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int i = 0;
while (i < n)
{
int max = a[i];
int s = check(i,a);
i++;
while (i<n && check(i,a)== s) {
if (a[i] > max)max = a[i];
i++;
}
b.push_back(max);
}
int s = 0;
for (int k = 0; k< b.size(); k++) {
s += b[i];
}
cout << s << endl;
}
}
I have debugged your code and also the modified code has been accepted for the above question.
Mistakes you made:
1. In the below loop, value at i'th index of vector<int> b is being added to long int s. Instead, b[k] should be added to long int s because the variable being used in the loop is k not i.
for (int k = 0; k< b.size(); k++) {
s += b[i];
}
2. In the question, range of variable n is given as (1 ≤ n ≤ 2.10^5). So, it is safe to use int n instead of long int n. Also, when I submitted my code on codeforces it gave me signed integer overflow error when I used long int n.
3. You need to use long long s instead of long int s because the value of each element of array A lies between (−10^9 ≤ a[i] ≤ 10^9 , ai ≠ 0) and when we add the elements it can easily surpass int and long int ranges.
4. Although, the answer got accepted when I used vector<int> a in the function
int check(int i,vector<int> a) {
if (a[i] > 0) {
return 1;
}
else return 0;
}
But as the user Scheff has said and is correct that it comes with a penalty in space and time, you should use call by reference i.e. vector<int> &a.
Modified Code:
#include <iostream>
#include <stdlib.h>
#include<vector>
using namespace std;
int check(int i, vector<int> &a) {
if (a[i] > 0) {
return 1;
}
else return 0;
}
int main() {
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
vector<int> a(n), b;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int i = 0;
while (i < n)
{
int max = a[i];
int s = check(i,a);
i++;
while ((i<n) && (check(i,a)== s)) {
if (a[i] > max)
max = a[i];
i++;
}
b.push_back(max);
}
long long s = 0;
for (int k = 0; k< b.size(); k++) {
s += b[k];
}
cout << s << endl;
}
}
Screenshot of Accepted Answer:

how to Calculate this series

#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;
}

LAP algorithm not working with large numbers

include
#include <fstream>
#include <algorithm>
using namespace std;
long int lenghtOfLongestAP(long int set[],long int n)
{
if (n <= 2) return n;
long int L[n][n];
long int llap = 2;
for (long int i = 0; i < n; i++)
L[i][n-1] = 2;
for (long int j=n-2; j>=1; j--)
{
int i = j-1, k = j+1;
while (i >= 0 && k <= n-1)
{
if (set[i] + set[k] < 2*set[j])
k++;
else if (set[i] + set[k] > 2*set[j])
{ L[i][j] = 2, i--; }
else
{
L[i][j] = L[j][k] + 1;
llap = max(llap, L[i][j]);
i--; k++;
}
}
while (i >= 0)
{
L[i][j] = 2;
i--;
}
}
return llap;
}
int main()
{
ofstream cout("Output.txt");
ifstream cin("cablecar-sub4-attempt3.txt");
int ab;
cin >> ab;
for (long int z = 0; z < ab; z++)
{
long int bs;
cin >> bs;
long int array[bs];
for(long int h = 0; h<bs; h++)
cin >> array[h];
sort(array, array + bs);
cout << "Case #" << z+1 << ": " << lenghtOfLongestAP(array, bs) << endl;
}
return 0;
}
This is my code. It is a LAP (Largest arithmetic progression) algorithm, so it finds the largest progression in an sorted array. I have the following set of data:
pastebin.com/77meKfKW
Strangely, the program crashes after case 30, which it shouldn't. What kind of problem might it be and how can I fix it?
This is probably a stack overflow. You are allocating your array on the stack with 267*267 entries which uses a lot of memory.
Try allocating the memory on the heap instead, or simply changing the array from being local to being global (with a fixed maximum value of n).
e.g.
change
long int lenghtOfLongestAP(long int set[],long int n)
{
if (n <= 2) return n;
long int L[n][n];
to
long int L[1000][1000]; // or whatever your maximum n might be
long int lenghtOfLongestAP(long int set[],long int n)
{
if (n <= 2) return n;