How to find the Nth number in a fractal sequence? - c++

The assignment is to write a C++ program which takes the input number n and outputs the nth number in the sequence:
1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6 ...
This is what I've come up with so far:
#include <iostream>
using namespace std;
int main()
{
long long n,k=1,result;
cin >> n;
if(n==1){
result=1;
}else{
for(int i=1,j=1;;i=j,j=j+k){
if(n>i&&n<=j){
result=n-i;
break;
}else{
k++;
}
}
}
cout << result << endl;
}
This is also what I've written before:
#include <iostream>
using namespace std;
int main()
{
long long n,count=0,result;
cin >> n;
for(int i=1;;i++){
for(int j=1;j<=i;j++){
count=count+1;
if(count==n){
result=j;
break;
}
}
if(count>=n){
break;
}
}
cout << result << endl;
}
Both of these work properly for smaller numbers, but the problem is I have to follow the constraint:
1 <= n <= 10^12
So when bigger numbers are inputted, the programs both take too long to output the solution and exceed the time limit, which is 2 seconds. I've been working on this for 5 hours now and I don't know how to improve these programs so they are faster. I also thought about a certain formula that could help determine the nth number in such a sequence, but I can't seem to find anything about it on the internet or in my math books. Could somebody point me to the solution? I would be very grateful.

We can group numbers in your sequence:
(1) (1, 2) (1, 2, 3) ...
The overall amount of numbers is
1 + 2 + 3 + ...
The latter is an arithmetic progression, its sum equals to x*(x+1)/2.
We'll find the number of full groups k that go before n+1-th number in the sequence. k equals to the maximal integer such that k*(k+1)/2 <= n. To find it we'll solve the quadratic equation:
x*(x+1)/2 = n
x^2 + x - 2*n = 0
Let's assume that positive root of this equation is x'. We round it down to the nearest integer k. If x' == k (x' is a whole number) it is the answer. Otherwise, the answer is n - k*(k+1)/2.
Exemplary c++ implementation:
double d = 1 + 8.0 * n;
double x = (-1 + sqrt(d)) / 2;
long long k = floor(x);
long long m = k*(k+1) / 2;
if (m == n) {
return k;
} else {
return n - m;
}
The solution has O(1) time complexity.

The first job is to write out the sequence like this:
1
2 3
4 5 6
7 8 9 10
And note that we want to map this to
1
1 2
1 2 3
1 2 3 4
The row position of a number is given by rearranging the formula for an arithmetic progression, solving the resultant quadratic, discarding the negative root, and removing any fractional part of the answer. A number t appears in the row r given by the whole number part
r = R(1/2 + (1/4 + 2 * (t - 1))1/2)
Where R() is a function that rounds a number downwards to the whole number.
But you are after the column c. That is obtained subtracting the value of the first term in that row from t:
c = t - 1/2 * r * (r - 1)
Reference: https://en.wikipedia.org/wiki/Arithmetic_progression

A solution using loop. It will out the number at nth.
x = 0 ;
i = 1 ;
do {
x += i ;
if( x == n ) {
cout<< i ;
break ;
}
else if( x > n ) {
cout<< (n - (x-i)) ;
break ;
}
i ++ ;
}while( 1) ;

Related

Making a factorial program faster?

I've been trying to submit this to a website with programming lessons, but the judge keeps telling me that this program takes too long to execute :/
Problem Statement:
Write a program that reads a non-negative integer n from the standard input, will count the digit of tens and the digit of ones in the decimal notation of n!, and will write the result to the standard output. In the first line of input there is one integer D (1≤D≤30), denoting the number of cases to be considered. For each case of entry. your program should print exactly two digits on a separate line (separated by a single space): the tens digit and the ones digit of n! in the decimal system.
Input/Output:
Input
Output
2
1
0 1
4
2 4
#include <iostream>
using namespace std;
int d,n;
int main()
{
cin>>d;
for(int i=0; i<d; i++)
{
cin>>n;
int silnia = 1;
for(int j=n; j>1; j--)
{
silnia=silnia*j;
}
if(silnia == 1) cout<<0<<" "<<silnia<<"\n";
else cout<<(silnia/10)%10<<" "<<silnia%10<<"\n";
}
return 0;
}
You can get rid of inner loop since n! == (n - 1)! * n:
cin >> d;
int factorial = 1;
cout << 0 << " " << 1 << "\n";
for (int i = 1; i < d; ++i) {
/* we operate with last two disgits: % 100 */
factorial = (factorial * i) % 100;
cout << factorial / 10 << " " << factorial % 10 << "\n";
}
Edit: Another issue is with
silnia=silnia*j;
line. Factorial grows fast:
13! = 6227020800 > LONG_MAX (2147483647)
that's why we should use modulo arithmetics: we keep not factorial itself (which can be very large), but its two last digits (note % 100), which is garanteed to be in 00..99 range:
factorial = (factorial * i) % 100;
Or even (if i can be large)
factorial = (factorial * (i % 100)) % 100;
Since only the last 2 digits of n! are needed, any n >= 10** will have a n! with 00 as the last 2 digits.
A short-cut is to test n: This takes the problem from O(n) to O(1).
int factorial = 0;
if (n < 10) {
int factorial = 1;
for(int j=n; j>1; j--)
{
factorial *= j;
}
factorial %= 100;
}
Or use a look-up table for n in the [0...10) range to drop the for loop.
---
** 10_or_more! has a 2 * 5 * 10 * other factors in it. All these factorials then end with 00.

Prime number sum ,Though not really easy

Given a number n and integer k, check whether k prime number sums to n or not.
input 13 2
output: yes
explanation: 11+2 equals 13
since k is assumed to be any general integer, I don't know how to solve it. I thought to solve it by creating set of all prime number and looking for k number but even if k is as small as 5 we have to run 4 to 5 loop to do it. how to approach such problem, kindly looking for help,thanks.
I tried initial code as:
#include<iostream>
#include<unordered_set>
#include<vector>
using namespace std;
bool is_prime(int n){
bool flag =true;
for(int i=2;i<n;i++){
if(n%i==0 && n!=i){
flag=false;
break;
}
}
if(flag){
return true;
}
return false;
}
int main(){
int n;cin>>n;
int k;cin>>k;
unordered_set<int>s;
for(int i=2;i<n;i++){
if(is_prime(i)){
s.insert(i);
}
}
}
This can be solved by assuming Goldbach's conjecture. Goldbach's conjecture says:
Any even integer is the sum of two prime numbers
We can exploit this to create the following rules:
If n < 2k then NO (because 2 is the smallest prime)
If k == 1 then YES IFF n is prime
If n >= 2k and k == 2 THEN YES if n is even (Goldbach) , If n is odd then NO iff n-2 is not a prime number
If n >= 2k and k >= 3 THEN Always YES:
When n is even, it can be expressed as 2 + ... + 2 + (n - 2 * (k - 2)),
n - 2 * (k - 2) is also even and can be expressed as a sum of two primes (by Goldbach),
When n is odd, it can be expresses as 3 + 2 + ... + 2 + (n - 3 - 2 * (k - 3)),
n - 3 - 2 * (k - 3) is even and can be expressed by sum of two primes (Goldbach).

How to make my code about 'arithmetic substrings' work quicker

I have some problems with code for my classes. Even though it works correctly, I run out of time for half of the examples.
Here's the task (I really did my best trying to translate it):
You have a permutation of numbers 1,2,...,n for some n. All consecutive numbers of permutations together create sequence a1, a2, an. Your task is to count, how many arithmetic substrings of a sequence of length 3 exist.
Input:
In first line there is a number n (1 <= n <= 200 000). In the second line there is n numbers a1, a2...an representing our permutation.
Output:
The program needs to print out amount of arithmetic substrings of length 3 for permutations from entry. You can assume that the result won't be bigger than 1 000 000.
Is there any way to make it work faster? Thanks for help!
#include <iostream>
using namespace std;
int main()
{
int input_length;
cin >> input_length;
int correct_sequences = 0;
bool* whether_itroduced = new bool[input_length + 1]{0}; // true - if number was already introduced and false otherwise.
for (int i = 0; i < input_length; i++)
{
int a;
cin >> a;
whether_itroduced[a] = true;
int range = min(input_length - a, a - 1); // max or min number that may be in the subsequence e.g. if introduced number a = 3, and all numbers are six, max range is 2 (3 - 2 = 1 and 3 + 2 = 5, so the longest possible subsequence is 1, 3, 5)
for (int r = range * -1; r <= range; r++) // r - there is a formula used to count arithmetic sequences -> an-1 = a1-r, an = a1, an+1 = a1+r, I have no idea how to explain it
{
if (r == 0) continue; // r cannot be 0
if (whether_itroduced[a - r] && !whether_itroduced[a + r])
correct_sequences++;
}
}
cout << correct_sequences;
}
example
input:
5
1 5 4 2 3
output:
2
// 1,2,3 and 5,4,3

Sequence of n numbers - compute all possible k-subsequence of "lucky" numbers

I have a problem with one task, so if you could help me a little bit.
Numbers are "lucky" or "unlucky". Number is "lucky" just if every
digit 7
or every digit is 4. So "lucky" numbers are for example 4, 44, 7, 77.
"Unlucky" are the others numbers.
You will get sequence of n-elements and number K. Your task is to
compute number of all possible k-elements subsequence, which fulfill a one
condition. The condition is that in the subsequence mustn't be two same "lucky"
numbers. So for example there mustn't 77 and 77...
Output number of all possible k-elements subsequence mod 10^9+7
0 < N,K < 10^5
Few examples:
Input:
5 2
7 7 3 7 77
Output:
7
Input:
5 3
3 7 77 7 77
Output:
4
Input:
34 17
14 14 14 ... 14 14 14
Output:
333606206
I have code which seems to work, but it is too slow when I try to compute binomial coefficient. I'm using map. In string I store number in string format. In second - int - part of the map is number which represents how many times was that number(in the first map parameter) used. So now I have stored every "unlucky" numbers stored together. Also every same "lucky" number is together. When I have it stored like this, I just compute all multiplications. For example:
Input
5 2
3 7 7 77 7
Are stored like this: map["other"] = 1 map["7"] = 3 map["77"] = 1
Because k = 2 --> result is: 1*3 + 1*1 + 1*3 = 7.
I think problem is with computing binomial coefficient. For the third example it needs to compute (34 choose 17) and it is computing very long time.I've found this article and also this , but I don't understand how they are solving this problem.
My code:
#include<iostream>
#include<string>
#include<map>
#include <algorithm>
#include <vector>
using namespace std;
int binomialCoeff(int n, int k)
{
// Base Cases
if (k == 0 || k == n)
return 1;
// Recur
return binomialCoeff(n - 1, k - 1) + binomialCoeff(n - 1, k);
}
int main()
{
int n, k;
cin >> n >> k;
map<string, int> mapa; // create map, string is a number, int represents number of used string-stored numbers ---> so if 7 was used two times, in the map it will be stored like this mapa["7"] == 2 and so on)
for (int i = 0; i < n; i++) // I will load number as string, if this number is "lucky" - digist are all 7 or all 4
{ // every "unlucky" numbers are together, as well as all same "lucky" numbers ---> so 77 and 77 will be stored in one element....
string number;
cin >> number;
char digit = number[0];
bool lucky = false;
if (digit == '7' || digit == '4')
lucky = true;
for (int j = 1; j < number.length(); j++) {
if (digit != '7' && digit != '4')
break;
if (number[j] != digit) {
lucky = false;
break;
}
}
if (lucky)
mapa[number]++;
else
mapa["other"]++;
}
vector<bool> v(mapa.size());
bool lack = k > mapa.size(); //lack of elements in map --> it is when mapa.size() < k; i. e. number of elements in array can't make k-element subsequence.
int rest = lack ? k - mapa.size() + 1 : 1; // how many elements from "unlucky" numbers I must choose, so it makes base for binomial coefficient (n choose rest)
if (lack) //if lack is true, different size of vector
fill(v.begin() + mapa.size(), v.end(), true);
else
fill(v.begin() + k, v.end(), true);
int *array = new int[mapa.size()]; //easier to manipulate with array for me
int sum = 0;
int product = 1;
int index = 0;
for (map<string, int> ::iterator pos = mapa.begin(); pos != mapa.end(); ++pos) // create array from map
{
if (lack && pos->first == "other") { //if lack of elements in map, the number in elemets representing "unlucky" numbers will be binomial coefficient (mapa["other] choose rest)
array[index++] = binomialCoeff(mapa["other"], rest);
continue;
}
array[index++] = pos->second;
}
do { // this will create every posible multiplication for k-elements subsequences
product = 1;
for (int i = 0; i < mapa.size(); ++i) {
if (!v[i]) {
product *= array[i];
}
}
sum += product;
} while (next_permutation(v.begin(), v.end()));
if (mapa["other"] >= k && mapa.size() > 1) { // if number of "unlucky" numbers is bigger than k, we need to compute all possible k-elements subsequences just from "unlucky" number, so binomial coefficient (mapa["other] choose k)
sum += binomialCoeff(mapa["other"], k);
}
cout << sum % 1000000007 << endl;
}

Finding total number of unique factorization

I want to find total factors of any number.
In number theory, factorization is the breaking down of a composite number into smaller non-trivial divisors, which when multiplied together equal the original integer. Your job is to calculate number of unique factorization(containing at least two positive integers greater than one) of a number.
For example: 12 has 3 unique factorizations: 2*2*3, 2*6, 3*4 . Note:
3*4 and 4*3 are not considered different.
I have attempted to find that but not getting exact for all.
Here is my code :
#include<iostream>
using namespace std;
int count=0;
void factor(int n,int c,int n1)
{
for(int i=n1; i<n ; i++)
{
if(c*i==n)
{count++;
return;}
else
if(c*i>n)
return;
else
factor(n,c*i,i+1);
}
return;
}
int main()
{
int num,n;
cin>>num;
for(int i=0 ; i<num ; i++)
{
cin>>n;
count=0;
factor(n,1,1);
cout<<count<<endl;
}
return 0;
}
Input is number of test cases followed by test-cases(Numbers).
Example : Input: 3 12 36 3150
Output: 3 8 91
I think you are looking for number of factorizations of a number which are unique.
For this I think you need to find the count of number of prime factor of that number. Say for
12 = 2, 2, 3
Total count = 3;
For 2, 2, 3 we need
(2*2)*3 ~ 4*3
2*(2*3) ~ 2*6
2*2*3 ~ 2*2*3
To solve this we have idea found in Grimaldi, discrete and combinatorial mathematics.
To find number of ways of adding to a number(n) is 2^(n-1) -1. For 3 we have...
3 =
1+1+1
2+1
1+2
Total count = 2^(3-1) -1 = 4-1 = 3
We can use analogy to see that
1+1+1 is equivalent to 2*2*3
1+2 is equivalent to 2*(2*3)
2+1 is equivalent to (2*2)*3
Say number of prime factors = n
So we have number of factorizations = 2^(n-1)-1
The code:
#include <stdio.h>
int power(int x, int y)
{
int prod =1, i ;
for(i=1; i<=y;i++) prod *= x;
return prod;
}
int main()
{
int number,div;
int count = 0, ti, t;
printf("Input: ");
scanf("%d",&t);
for(ti=1; ti<=t;ti++)
{
scanf("%d", &number);
div = 2;count = 0;
while(number != 0)
{
if(number%div!=0) div = div + 1;
else
{
number = number / div;
//printf("%d ",div);
count++;
if(number==1) break;
}
}
printf("%d ", power(2,count-1)-1);
}
return 0;
}
Using mod is really useful in attempting to factor:
for(int i = 1; i <= fnum; ++i){ //where fnum is the number you wish to factor
if(!(fnum % i)) ++count;
}
return count;
Of cross this is the number of factors, not unique factors, if you want the number of unique factors, you have to do some additional work.
The solution is to realize that of all permutations, precisely one is sorted. 2 * 4 * 7 * 3 gives the same result as 2 * 3 * 4 * 7. That means that when you've found one factor, you should not check the remainder for lower factors. However, you should check if the same factor appears again: 12 = 2 * 2 * 3. The sequence 2 2 3 is also sorted.
BTW, you should give your variables clearer names, or at least add some comments describing them.