Write a function that, given a list of non-negative integers, arranges them such that they form the largest possible number. For example, given [0, 1, 2, 3], the largest formed number is 3210.
Logic I understand:
We compare two numbers XY (Y appended at the end of X) and YX (X appended at the end of Y). If XY is larger, then X should come before Y in output, else Y should come before. For example, let X and Y be 542 and 60. To compare X and Y, we compare 54260 and 60542. Since 60542 is greater than 54260, we put Y first. I can also write code for this.
What surprises me is this solution:
#include <stdio.h>
#include<stdlib.h>
int swap(const void *c, const void *d) {
int n1 = *(int*)c;
int n2 = *(int*)d;
int a = pow(10, floor(log10(n2)) + 1) * n1 + n2;
int b = pow(10, floor(log10(n1)) + 1) * n2 + n1;
if (n1 == 0) return 1;
if (a < b) return 1;
return 0;
}
int main() {
int t = 0, tc = 0;
scanf("%d", &t);
for(tc = 1; tc <= t; tc++) {
int n;
scanf("%d",&n);
int arr[n];
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
qsort(arr, n, sizeof(int), swap);
for (int i = 0; i < n; i++)
printf("%d", arr[i]);
printf("\n");
}
return 0;
}
To my surprise, it passes all the test cases. Can anyone explain to me this logic?
This does exactly what you described:
int a = pow(10, floor(log10(n2)) + 1) * n1 + n2;
int b = pow(10, floor(log10(n1)) + 1) * n2 + n1;
If we're passed in X and Y, then a is XY, and b is YX.
If you're concatenating 2 and 34, you need to multiply 2 by 100 (to get 200) and then add 34 (to get 234). Where did the 100 come from? It's 10 to the power of the number of digits in 34. To get the number of digits, we compute the base-10 logarithm of 34 and round it up.
So:
log10(34) ~= 1.5
floor(log10(34)) == 1
floor(log10(34)) + 1 == 2
10^2 = 100, so now we know what to multiply the first number by before adding the second.
The second line does the same thing with the variables in the opposite order (computing YX concatenated).
Finally, we return 1 if a < b and 0 otherwise. This makes it a working comparator for a sort function:
if (a < b) return 1;
EDIT
I'm not sure what this line is doing:
if (n1 == 0) return 1;
I think it may be protecting us from the result of log10(0). (I'm not sure what that returns... the mathematical result is negative infinity.)
Basically, the result of this in the comparator is "Put n2 first if n1 is 0," which is always right. (I'm just not 100% sure why it's needed.)
Let's say that an array arr[] is the solution to your problem, i.e. its elements are arranged in such a way as to produce the max result M. Therefore, swapping arbitrary array elements i and j cannot yield a result that would be greater than M.
Consider comparing arbitrary indexes i and j in your comparator function swap, and digits surrounding them:
XXXXXXXX IIIIII XXXXXXXXXXXXXXXX JJJJJJ XXXXXXXXX
-------- ------ ---------------- ------ ---------
arr[...] arr[i] arr[...] arr[j] arr[...]
Note that if IIIIII block sorts before JJJJJJ block, it would continue sorting ahead of it regardless of the content of the X blocks. Therefore, comparing individual elements of arr in isolation produces an optimal solution when the entire array is sorted using this comparison.
Your comparator implementation performs this logic using "decimal shifting": if you want to add digits of x behind digits of y, you need to decimal-shift y by the number of digits in the x. The number of digits in the x can be determined as log10(x); decimal shifting left by k positions is achieved by multiplying y by 10k.
Note: This line
if (n1 == 0) return 1;
should be at the top, before you call decimal logarithm. There should also be another line
if (n2 == 0) return 0;
to ensure that we do not pass zero to log10.
What has been done in the code is,
Take input the array
Sort it descending order
Output it
The input & output part is easy to understand.
Now the sorting is done using qsort which accepts a compare function. In the code though the function is named swap, it is actually a compare function - which returns 1 when the first element is greater then the second one. Otherwise returns 0. Like is 54 > 45? and is 45>54?
Now, why a descending sort gives the deserved output? Let's see an example:
54 > 45 , This means if the big number is a left position the number is greater. A descending sort keeps the greater number left.
You already have some very good explanations of why the code you posted works. However, it should be noted that this method suffers from overflow whenever the decimal shifted version of any number exceeds the max representable int. If we assume a 32-bit int then this has 10 digits (2147483647), so comparing relatively small numbers such as 32412 and 12345 will cause problems.
As an alternative we can compare the numbers directly using a recursive function. Let the two numbers be n1 and n2, with d1 and d2 digits respectively. Our comparison function needs to handle three cases:
If d1 == d2we compare n1 and n2 directly, e.g. 345 and 463
If d1 < d2 we compare n1 to the d1 high-order digits of n2, e.g. for 37 and 398 we compare 37 and 39. If these are equal, we recursively compare n1 with the d2-d1 low-order digits of n2. So for 37 and 378 we'd compare 37 and 8.
If d1 > d2 we can swap n1 and n2 and compare as per case 2, though we then have to reverse the order of the result.
Here's some code to illustrate.
int swap(const void *c, const void *d)
{
int n1 = *(int*)c;
int n2 = *(int*)d;
int d1 = numDigits(n1);
int d2 = numDigits(n2);
return compare0(n1, d1, n2, d2);
}
int compare0(int n1, int d1, int n2, int d2)
{
if (d1 == d2)
return n2 - n1;
else if (d1 < d2)
return compare1(n1, d1, n2, d2);
else
return -compare1(n2, d2, n1, d1);
}
int compare1(int n1, int d1, int n2, int d2)
{
int pd = (int) pow(10, d2 - d1);
int nh2 = n2 / pd;
if (n1 == nh2)
return compare0(n1, d1, n2 % pd, d2 - d1);
else
return nh2 - n1;
}
int numDigits(int n)
{
return (n == 0) ? 1 : 1 + (int) log10(n);
}
Related
Task description:
Calculate the sum of the first n elements of a series s1, s2 = s1 + d1, s3 = s2 + d2, ...
where the differences d1, d2, ... between the elements form a geometric series.
The function receives the first three elements of the series (first, second and third) as well as n values.
The return value of the function is the sum s1 + ... + sn.
The nth element of the geometric series: dn = d1 * q ^ (n-1)
The first test case:
struct {double first; double second; double third; int n; double sum;} testlist[1] = {
{1.0, 3.0, 7.0, 5, 57.0},
{1.0, 2.0, 2.5, 5, 11.125}
My code is: (with the help of Oli L)
double series(double first, double second, double third, int n) {
if(n <= 0) return 0;
double d1 = second-first;
double d2 = third-second;
double q = d2/d1;
double s[n];
double d[n];
double result = q;
s[0] = first;
d[0] = d1;
double sum = s[0];
for( int i = 1 ; i < n ; i++) {
d[i] = d1*result;
result*=q;
s[i] = s[i-1] + d[i-1];
sum += s[i];
}
return sum;
}
Unfortunately, I don’t see any more test cases and I can’t extract the main function either, as I have to upload my code to a strict page that tests it after pasting it into the encrypted frame.
So far, with a little help, I've gotten as far as I can, 4 out of 5 test cases run successfully, but one (which I don't see) isn't good. I would ask for ideas on what the problem might be, what an extreme case I might not have thought, or what the code might look like then.
The sequence 0, 0, 0,… is a geometric sequence (it satisfies di = d1•qi−1 by using 0 for q) that is not handled by the code in the question. For this series of differences, all the si are equal. Notably, first, second, and third have the same value.
When this occurs, d1 and d2 are set to 0 by these lines:
double d1 = second-first;
double d2 = third-second;
and then double q = d2/d1; sets q to a NaN (Not a Number, a “value” used in floating-point to indicate there is no suitable real number). This NaN propagates through other calculations, causing the routine to return a NaN.
When the sequence is a sequence of identical terms with zero differences, the sum of n terms is n*first. So the code in the question can be corrected by handling this case just after the test for n <= 0:
if (first == second && second == third)
return n*first;
Here is a code to exponentiate a number to a given power:
#include <stdio.h>
int foo(int m, int k) {
if (k == 0) {
return 1;
} else if (k % 2 != 0) {
return m * foo(m, k - 1);
} else {
int p = foo(m, k / 2);
return p * p;
}
}
int main() {
int m, k;
while (scanf("%d %d", &m, &k) == 2) {
printf("%d\n", foo(m, k));
}
return 0;
}
How do I calculate the time complexity of the function foo?
I have been able to deduce that if k is a power of 2, the time complexity is O(log k).
But I am finding it difficult to calculate for other values of k. Any help would be much appreciated.
How do I calculate the time complexity of the function foo()?
I have been able to deduce that if k is a power of 2, the time complexity is O(logk).
First, I assume that the time needed for each function call is constant (this would for example not be the case if the time needed for a multiplication depends on the numbers being multiplied - which is the case on some computers).
We also assume that k>=1 (otherwise, the function will run endlessly unless there is an overflow).
Let's think the value k as a binary number:
If the rightmost bit is 0 (k%2!=0 is false), the number is shifted right by one bit (foo(m,k/2)) and the function is called recursively.
If the rightmost bit is 1 (k%2!=0 is true), the bit is changed to a 0 (foo(m,k-1)) and the function is called recursively. (We don't look at the case k=1, yet.)
This means that the function is called once for each bit and it is called once for each 1 bit. Or, in other words: It is called once for each 0 bit in the number and twice for each 1 bit.
If N is the number of function calls, n1 is the number of 1 bits and n0 is the number of 0 bits, we get the following formula:
N = n0 + 2*n1 + C
The constant C (C=(-1), if I didn't make a mistake) represents the case k=1 that we ignored up to now.
This means:
N = (n0 + n1) + n1 + C
And - because n0 + n1 = floor(log2(k)) + 1:
floor(log2(k)) + C <= N <= 2*floor(log2(k)) + C
As you can see, the time complexity is always O(log(k))
O(log(k))
Some modification added to output a statistics for spread sheet plot.
#include <stdio.h>
#include <math.h>
#ifndef TEST_NUM
#define TEST_NUM (100)
#endif
static size_t iter_count;
int foo(int m, int k) {
iter_count++;
if (k == 0) {
return 1;
} else if(k == 1) {
return m;
} else if (k % 2 != 0) {
return m * foo(m, k - 1);
} else {
int p = foo(m, k / 2);
return p * p;
}
}
int main() {
for (int i = 1; i < TEST_NUM; ++i) {
iter_count = 0;
int dummy_result = foo(1, i);
printf("%d, %zu, %f\n", i, iter_count, log2(i));
}
return 0;
}
Build it.
gcc t1.c -DTEST_NUM=10000
./a > output.csv
Now open the output file with a spread sheet program and plot the last two output columns.
For k positive, the function foo calls itself recursively p times if k is the p-th power of 2. If k is not a power of 2, the number of recursive calls is strictly inferior to 2 * p where p is the exponent of the largest power of 2 inferior to k.
Here is a demonstration:
let's expand the recursive call in the case k % 2 != 0:
int foo(int m, int k) {
if (k == 1) {
return m;
} else
if (k % 2 != 0) { /* 2 recursive calls */
// return m * foo(m, k - 1);
int p = foo(m, k / 2);
return m * p * p;
} else { /* 1 recursive call */
int p = foo(m, k / 2);
return p * p;
}
}
The total number of calls is floor(log2(k)) + bitcount(k), and bitcount(k) is by construction <= ceil(log2(k)).
There are no loops in the code and the time of each individual call is bounded by a constant, hence the overall time complexity of O(log k).
The number of times the function is called (recursively or not) per power call is proportional to the minimum number of bits in the exponent required to represent it in binary form.
Each time you enter in the function, it solves by reducing the number by one if the exponent is odd, OR reducing it to half if the exponent is even. This means that we will do n squares per significant bit in the number, and m more multiplications by the base for all the bits that are 1 in the exponent (which are, at most, n, so m < n) for a 32bit significant exponent (this is an exponent between 2^31 and 2^32 the routine will do between 32 and 64 products to get the result, and will reenter to itself a maximum of 64 times)
as in both cases the routine is tail-recursive, the code you post can be substituted with an iterative code in which a while loop is used to solve the problem.
int foo(int m, int k)
{
int prod = 1; /* last recursion foo(m, 0); */
int sq = m; /* squares */
while (k) {
if (k & 1) {
prod *= sq; /* foo(m, k); k odd */
}
k >>= 1;
sq *= sq;
}
return prod; /* return final product */
}
That's huge savings!!! (between 32 multiplications and 64 multiplications, to elevate something to 1,000,000,000 power)
[Hardy about Ramanujan]: I remember once going to see him when he was ill at Putney. I had ridden in taxi cab number 1729 and remarked that the number seemed to me rather a dull one, and that I hoped it was not an unfavourable omen. "No," he replied, "it is a very interesting number; it is the smallest number expressible as the sum of two cubes in two different ways."
The two different ways are 1³ + 12³ and 9³ + 10³
I'm writing a series of functions (in C) to calculate different things related to Ramanujan's numbers. I'm now trying to write a function that returns the i-th Ramanujan's number. Since I've already created a function that checks whether a number is a Ramanujan number or not, the easy way would be to check every number, from 0 to infinity. If a given number is a Ramanujan number, increment a counter by one. Once the counter equals the index I'm looking for, I return the number. In code:
unsigned long ramanujan_index (unsigned long x, int counter, int index)
{
if (counter == index)
return x - 1;
if (is_ramanujan(x))
return ramanujan_index(x + 1, counter + 1, index);
else
return ramanujan_index(x + 1, counter, index);
}
It works, sure, but I'm a little worried that it's not as efficient as it could possibly be. Checking every number doesn't seem like the best solution. More so if we consider the first number is 1729, and the second is 4104. It seems that it'd take quite a lot of steps to find the 5th Ramanujan number (32832 steps, actually, since it has to check every number from 0 to 32832, which is the 5th number). Is there a better way to do so?
Here is a simple program using nested loops to enumerate Ramanujan numbers of different orders. It uses an array to store the number of ways and enumerates cubes to generate sums. The computation is performed in slices to take advantage of CPU caches and allow for ranges that exceed memory size.
This program enumerates Ramanujan numbers of order 2 up to 1 million in less than 0.01s and finds the smallest Ramanujan number of order 4 in a few hours: 6963472309248
#include <stdio.h>
#include <stdlib.h>
#define MAX_SLICE 0x400000 // use 4MB at a time
int main(int argc, char **argv) {
int order = 2;
size_t min = 0, max = 1000000, a, a3, b, n, i, n1, n2;
while (*++argv) {
char *p;
n = strtoull(*argv, &p, 0);
if (*p == '-') {
min = n;
max = strtoull(p + 1, NULL, 0);
} else {
if (n < 10)
order = n;
else
max = n;
}
}
for (n1 = min; n1 <= max; n1 = n2) {
size_t slice = (max + 1 - n1 <= MAX_SLICE) ? max + 1 - n1 : MAX_SLICE;
unsigned char *count = calloc(slice, 1);
n2 = n1 + slice;
for (a = 1; (a3 = a * a * a) < n2; a++) {
if (a3 + a3 >= n1) {
for (b = 1; b <= a && (n = a3 + b * b * b) < n2; b++) {
if (n >= n1)
count[n - n1]++;
}
}
}
for (i = n1; i < n2; i++) {
if (count[i - n1] >= order)
printf("%llu\n", (long long unsigned int)i);
}
free(count);
}
return 0;
}
Runs:
chqrlie$ time ./rama
1729
4104
13832
20683
32832
39312
40033
46683
64232
65728
110656
110808
134379
149389
165464
171288
195841
216027
216125
262656
314496
320264
327763
373464
402597
439101
443889
513000
513856
515375
525824
558441
593047
684019
704977
805688
842751
885248
886464
920673
955016
984067
994688
real 0m0.008s
user 0m0.002s
sys 0m0.002s
chqrlie$ time ./rama 10000000000 2 | wc -l
4724
real 0m7.526s
user 0m7.373s
sys 0m0.061s
chqrlie$ time ./rama 6963000000000-6964000000000 4
6963472309248
real 0m10.383s
user 0m10.243s
sys 0m0.050s
I am trying to solve this problem:
Input: the first line contains an integer T which represents the total cases you need to solve. Each test case contains P and Q, separated by space, represent the number you need to work on.
Output: print the result which is calculated from the multiplication of P and Q’s minimum factor and maximum prime factor.
Constraints: 1 ≤ 𝑇 ≤ 100 and 2 ≤ 𝑃,𝑄 ≤ 1000000
Sample Input: 2 210 84 6 12
Sample Output:
Case #1: 14
Case #2: 6
Explanation: Let’s take an example from the first case. The numbers 210 and 84 have several identical prime factors which are 2, 3, and 7. Number ‘2’ is the smallest common prime factor of the numbers, meanwhile number ‘7’ is their largest common prime factor. So, the result must be the multiplication of 2 and 7, which is 14.
Here's my code that I've been working, I tried to find factors from the given number the store the factors into array then check for the prime, but I feel that this isn't the right algorithm :(
void factor(int num1) {
int arrA[100000], a = 0, flag = 1;
//check factor
for (int i = 2; i <= num1; i++) {
if (num1 % i == 0) {
arrA[a] = i;
a++;
}
}
// check prime
for (int i = 0; i < a; i++) {
for (int j = 2; j < a; j++) {
if ((arrA[i] % j) == 0) {
flag = 0;
}
}
if (flag == 1) {
printf("%d ", arrA[i]);
}
flag = 1;
}
printf("\n");
}
Your function does not compute the prime factors correctly because it will find factors that are not prime. For num = 6, it will find 2, 3 but also 6.
You should divide num by i when you find that i divides num and otherwise increase i.
You can then make arrA much smaller as the maximum number of prime factors in an int is less than the number of bits in an int: 31 would suffice for 32-bit ints and 63 for 64-bit ints.
Once you have the prime factors of num, you should try and find the smallest and largest that divide the other number. Note that the first and last such prime numbers could be identical or might not even exist if the numbers have no common prime factor.
Note that you do not need to store the factors: for every prime factor of num, you can try and check if it divides the other number and keep the first one that does and the last one too.
Here is a simple implementation:
#include <stdio.h>
int main() {
int i, n, a, aa, b, p, p1, p2;
if (scanf("%d", &n) == 1) {
for (i = 1; i <= n; i++) {
if (scanf("%d%d", &a, &b) != 2)
break;
p1 = p2 = 1;
aa = a;
for (p = 2; p * p <= aa; p++) {
if (aa % p == 0) {
/* p is a prime factor of a */
if (b % p == 0) {
/* p is a common prime factor */
p2 = p;
if (p1 == 1) {
/* p is the smallest common prime factor */
p1 = p;
}
}
/* remove p as a factor of aa */
do { aa /= p; } while (aa % p == 0);
}
}
if (aa > 1) {
/* aa is the largest prime factor of a */
if (b % aa == 0) {
/* aa is the largest common prime factor */
p2 = aa;
if (p1 == 1) {
/* aa is also the smallest common prime factor */
p1 = aa;
}
}
}
/* print the product of the smallest and largest common prime factors */
/* if a == b and a is a large prime, a * a might overflow int */
printf("Case #%d: %lld\n", i, (long long)p1 * p2);
}
}
return 0;
}
I am trying to solve an online judge problem: http://opc.iarcs.org.in/index.php/problems/LEAFEAT
The problem in short:
If we are given an integer L and a set of N integers s1,s2,s3..sN, we have to find how many numbers there are from 0 to L-1 which are not divisible by any of the 'si's.
For example, if we are given, L = 20 and S = {3,2,5} then there are 6 numbers from 0 to 19 which are not divisible by 3,2 or 5.
L <= 1000000000 and N <= 20.
I used the Inclusion-Exclusion principle to solve this problem:
/*Let 'T' be the number of integers that are divisible by any of the 'si's in the
given range*/
for i in range 1 to N
for all subsets A of length i
if i is odd then:
T += 1 + (L-1)/lcm(all the elements of A)
else
T -= 1 + (L-1)/lcm(all the elements of A)
return T
Here is my code to solve this problem
#include <stdio.h>
int N;
long long int L;
int C[30];
typedef struct{int i, key;}subset_e;
subset_e A[30];
int k;
int gcd(a,b){
int t;
while(b != 0){
t = a%b;
a = b;
b = t;
}
return a;
}
long long int lcm(int a, int b){
return (a*b)/gcd(a,b);
}
long long int getlcm(int n){
if(n == 1){
return A[0].key;
}
int i;
long long int rlcm = lcm(A[0].key,A[1].key);
for(i = 2;i < n; i++){
rlcm = lcm(rlcm,A[i].key);
}
return rlcm;
}
int next_subset(int n){
if(k == n-1 && A[k].i == N-1){
if(k == 0){
return 0;
}
k--;
}
while(k < n-1 && A[k].i == A[k+1].i-1){
if(k <= 0){
return 0;
}
k--;
}
A[k].key = C[A[k].i+1];
A[k].i++;
return 1;
}
int main(){
int i,j,add;
long long int sum = 0,g,temp;
scanf("%lld%d",&L,&N);
for(i = 0;i < N; i++){
scanf("%d",&C[i]);
}
for(i = 1; i <= N; i++){
add = i%2;
for(j = 0;j < i; j++){
A[j].key = C[j];
A[j].i = j;
}
temp = getlcm(i);
g = 1 + (L-1)/temp;
if(add){
sum += g;
} else {
sum -= g;
}
k = i-1;
while(next_subset(i)){
temp = getlcm(i);
g = 1 + (L-1)/temp;
if(add){
sum += g;
} else {
sum -= g;
}
}
}
printf("%lld",L-sum);
return 0;
}
The next_subset(n) generates the next subset of size n in the array A, if there is no subset it returns 0 otherwise it returns 1. It is based on the algorithm described by the accepted answer in this stackoverflow question.
The lcm(a,b) function returns the lcm of a and b.
The get_lcm(n) function returns the lcm of all the elements in A.
It uses the property : LCM(a,b,c) = LCM(LCM(a,b),c)
When I submit the problem on the judge it gives my a 'Time Limit Exceeded'. If we solve this using brute force we get only 50% of the marks.
As there can be upto 2^20 subsets my algorithm might be slow, hence I need a better algorithm to solve this problem.
EDIT:
After editing my code and changing the function to the Euclidean algorithm, I am getting a wrong answer, but my code runs within the time limit. It gives me a correct answer to the example test but not to any other test cases; here is a link to ideone where I ran my code, the first output is correct but the second is not.
Is my approach to this problem correct? If it is then I have made a mistake in my code, and I'll find it; otherwise can anyone please explain what is wrong?
You could also try changing your lcm function to use the Euclidean algorithm.
int gcd(int a, int b) {
int t;
while (b != 0) {
t = b;
b = a % t;
a = t;
}
return a;
}
int lcm(int a, int b) {
return (a * b) / gcd(a, b);
}
At least with Python, the speed differences between the two are pretty large:
>>> %timeit lcm1(103, 2013)
100000 loops, best of 3: 9.21 us per loop
>>> %timeit lcm2(103, 2013)
1000000 loops, best of 3: 1.02 us per loop
Typically, the lowest common multiple of a subset of k of the s_i will exceed L for k much smaller than 20. So you need to stop early.
Probably, just inserting
if (temp >= L) {
break;
}
after
while(next_subset(i)){
temp = getlcm(i);
will be sufficient.
Also, shortcut if there are any 1s among the s_i, all numbers are divisible by 1.
I think the following will be faster:
unsigned gcd(unsigned a, unsigned b) {
unsigned r;
while(b) {
r = a%b;
a = b;
b = r;
}
return a;
}
unsigned recur(unsigned *arr, unsigned len, unsigned idx, unsigned cumul, unsigned bound) {
if (idx >= len || bound == 0) {
return bound;
}
unsigned i, g, s = arr[idx], result;
g = s/gcd(cumul,s);
result = bound/g;
for(i = idx+1; i < len; ++i) {
result -= recur(arr, len, i, cumul*g, bound/g);
}
return result;
}
unsigned inex(unsigned *arr, unsigned len, unsigned bound) {
unsigned i, result = bound, t;
for(i = 0; i < len; ++i) {
result -= recur(arr, len, i, 1, bound);
}
return result;
}
call it with
unsigned S[N] = {...};
inex(S, N, L-1);
You need not add the 1 for the 0 anywhere, since 0 is divisible by all numbers, compute the count of numbers 1 <= k < L which are not divisible by any s_i.
Create an array of flags with L entries. Then mark each touched leaf:
for(each size in list of sizes) {
length = 0;
while(length < L) {
array[length] = TOUCHED;
length += size;
}
}
Then find the untouched leaves:
for(length = 0; length < L; length++) {
if(array[length] != TOUCHED) { /* Untouched leaf! */ }
}
Note that there is no multiplication and no division involved; but you will need up to about 1 GiB of RAM. If RAM is a problem the you can use an array of bits (max. 120 MiB).
This is only a beginning though, as there are repeating patterns that can be copied instead of generated. The first pattern is from 0 to S1*S2, the next is from 0 to S1*S2*S3, the next is from 0 to S1*S2*S3*S4, etc.
Basically, you can set all values touched by S1 and then S2 from 0 to S1*S2; then copy the pattern from 0 to S1*S2 until you get to S1*S2*S3 and set all the S3's between S3 and S1*S2*S3; then copy that pattern until you get to S1*S2*S3*S4 and set all the S4's between S4 and S1*S2*S3*S4 and so on.
Next; if S1*S2*...Sn is smaller than L, you know the pattern will repeat and can generate the results for lengths from S1*S2*...Sn to L from the pattern. In this case the size of the array only needs to be S1*S2*...Sn and doesn't need to be L.
Finally, if S1*S2*...Sn is larger than L; then you could generate the pattern for S1*S2*...(Sn-1) and use that pattern to create the results from S1*S2*...(Sn-1) to S1*S2*...Sn. In this case if S1*S2*...(Sn-1) is smaller than L then the array doesn't need to be as large as L.
I'm afraid your problem understanding is maybe not correct.
You have L. You have a set S of K elements. You must count the sum of quotient of L / Si. For L = 20, K = 1, S = { 5 }, the answer is simply 16 (20 - 20 / 5). But K > 1, so you must consider the common multiples also.
Why loop through a list of subsets? It doesn't involve subset calculation, only division and multiple.
You have K distinct integers. Each number could be a prime number. You must consider common multiples. That's all.
EDIT
L = 20 and S = {3,2,5}
Leaves could be eaten by 3 = 6
Leaves could be eaten by 2 = 10
Leaves could be eaten by 5 = 4
Common multiples of S, less than L, not in S = 6, 10, 15
Actually eaten leaves = 20/3 + 20/2 + 20/5 - 20/6 - 20/10 - 20/15 = 6
You can keep track of the distance until then next touched leaf for each size. The distance to the next touched leaf will be whichever distance happens to be smallest, and you'd subtract this distance from all the others (and wrap whenever the distance is zero).
For example:
int sizes[4] = {2, 5, 7, 9};
int distances[4];
int currentLength = 0;
for(size = 0 to 3) {
distances[size] = sizes[size];
}
while(currentLength < L) {
smallest = INT_MAX;
for(size = 0 to 3) {
if(distances[size] < smallest) smallest = distances[size];
}
for(size = 0 to 3) {
distances[size] -= smallest;
if(distances[size] == 0) distances[size] = sizes[size];
}
while( (smallest > 1) && (currentLength < L) ) {
currentLength++;
printf("%d\n", currentLength;
smallest--;
}
}
#A.06: u r the one with username linkinmew on opc, rite?
Anyways, the answer just requires u to make all possible subsets, and then apply inclusion exclusion principle. This will fall well within the time bounds for the data given. For making all possible subsets, u can easily define a recursive function.
i don't know about programming but in math there is a single theorem which works on a set that has GCD 1
L=20, S=(3,2,5)
(1-1/p)(1-1/q)(1-1/r).....and so on
(1-1/3)(1-1/2)(1-1/5)=(2/3)(1/2)(4/5)=4/15
4/15 means there are 4 numbers in each set of 15 number which are not divisible by any number rest of it can be count manually eg.
16, 17, 18, 19, 20 (only 17 and 19 means there are only 2 numbers thatr can't be divided by any S)
4+2=6
6/20 means there are only 6 numbers in first 20 numbers that can't be divided by any s