Super rookie here. Just doing a little learning before my C course this semester. I found a book practice problem asking to categorize temperature values in an array. Here's everything I have:
// write program to process collection of daily high temps
#include <stdio.h>
int main (void)
{
int temp[26] = {55, 62, 68, 74, 59, 45, 41, 58, 60, 67,
65, 78, 82, 88, 91, 92, 90, 93, 87, 80,
78, 79, 72, 68, 61, 59};
int i;
float sum;
float avg;
int r1, r2, r3; // range 1, range 2, range 3
// Loop to catagorize temperature values
for(i = 0; i <= 26; i++)
{
if (temp[i] <= 60)
{
r1++;
}
else if ((temp[i] > 60) && (temp[i] <= 84))
{
r2++;
}
else
{
r3++;
}
}
printf("\nThe number of cold days are: %d", r1);
printf("\nThe number of pleasant days are: %d", r2);
printf("\nThe number of hot days are: %d", r3);
// Loop to take the average temperature
for (i = 0; i <= 25; i++)
{
sum = sum + temp[i];
avg = sum / i;
}
printf("\nThe average temperature of the set is: %f", avg);
return 0;
}
The average computes correctly, however, the codes is not categorizing the temp values in the array correctly. I just learned arrays yesterday. Can anyone help? Thanks!
You invoked undefined behavior:
1- by using uninitialized variables int r1, r2, r3; float sum; float avg;, you should initialize them as zeros.
2- by accessing if (temp[i] <= 60) in your loop for(i = 0; i <= 26; i++), while size of temp is 26 (should only access 0 - 25).
You should initialize sum, avg, r1, r2, r3 as 0. Also the range of your array is 0-25, so for(i = 0; i <= 26; i++) should be changed to for(i = 0; i <= 25; i++).
// write program to process collection of daily high temps
#include <stdio.h>
int main (void)
{
int temp[26] = {55, 62, 68, 74, 59, 45, 41, 58, 60, 67,
65, 78, 82, 88, 91, 92, 90, 93, 87, 80,
78, 79, 72, 68, 61, 59};
int i;
float sum = 0;
float avg = 0;
int r1 = 0, r2 = 0, r3 = 0; // range 1, range 2, range 3
// Loop to catagorize temperature values
for(i = 0; i <= 25; i++)
{
if (temp[i] <= 60)
{
r1++;
}
else if ((temp[i] > 60) && (temp[i] <= 84))
{
r2++;
}
else
{
r3++;
}
}
printf("The number of cold days are: %d\n", r1);
printf("The number of pleasant days are: %d\n", r2);
printf("The number of hot days are: %d\n", r3);
// Loop to take the average temperature
for (i = 0; i <= 25; i++)
{
sum = sum + temp[i];
avg = sum / i;
}
printf("The average temperature of the set is: %f\n", avg);
return 0;
}
For incrementing the value of a variable you need to initialize the value to the variable. In this case, the variables are r1,r2 & r3. The increment operator increases its value by 1. But if the value is not assigned before, the operator cant finds the value which would be increased.
Here r1++ similar to r1=r1+1.
so it should be initialized like
r1=0,r2=0,r3=0;
r1++; // which means r1=0+1=1
In addition to the existing solutions in the other answers, I propose this solution which introduces you to the concept of programming defensively. In this case I focus on defending against inconsistencies in non-trivial code.
#include <stdio.h>
int main (void)
{
int temp[/* auto */] = {55, 62, 68, 74, 59, 45, 41, 58, 60, 67, 65, 78, 82,
/* newline shows 2*13 */ 88, 91, 92, 90, 93, 87, 80, 78, 79, 72, 68, 61, 59 };
/* in case space allows, this allows humans to grasp the total number and e.g.
notice when the number of initialisers is incorrect; the compiler does not
mind of course */
int i=0; /* this init is paranoid, in case loop setup is unusually without init */
float sum = 0.0f; /* this init is needed, see other answers */
float avg = 0.0f; /* this init is needed, see other answers */
int r1 = 0, r2 = 0, r3 = 0; // range 1, range 2, range 3
size_t length = sizeof(temp)/sizeof(temp[0]); /* avoid need for magic numbers */
// Loop to catagorize temperature values
for(i = 0; i < length; i++) /* avoid need for magic numbers */
{
if (temp[i] <= 60)
{
r1++;
} else if (temp[i] <= 84) /* avoid copy of first treshold */
{
r2++;
} else
{
r3++;
}
}
printf("The number of cold days are: %d\n", r1);
printf("The number of pleasant days are: %d\n", r2);
printf("The number of hot days are: %d\n", r3);
// Loop to take the average temperature
for (i = 0; i < length; i++) /* avoid need for magic number */
{
sum = sum + temp[i];
avg = sum / i;
}
printf("The average temperature of the set is: %f\n", avg);
return 0;
}
You might notice that avoiding magic numbers (using <) and a habit of initialising everything would have prevented both problems discussed and solved in the other answers.
You could also introduce a chance that a human spots a mistake, by outputting a little additional information, assuming of course that it does not conflict with your requirements. In which case the additional output could be created in a way to be removable conveniently for delivery, in a generic way in your team. Without that removal mechanism, this demonstrates "unobtrusive" additional info in output (noticably exaggerated, I admit):
printf("The average temperature of the set of %i temperatures "
"(%i of which have been classified) is: %f\n", length, r1 + r2 + r3, avg);
The special way of aligning {} in if-else constructs is my favorite indentation style. In my opinion, but it is only an opinion, it also is defensive programming, because at least I do spot if-else-trees more easily like that and hence have a better chance of spotting mistakes. Using {} even for single-statement branches is also part of that, it defends against mistakes introduced by adding a statement to a single-statement else branch without {}.
Removing the logically unneeded (temp[i] > 60) && defends against mistakes like
if (temp[i] < 60)
{
r1++;
} else if ((temp[i] > 60) && (temp[i] < 84))
{
r2++;
} else
{
r3++;
}
Because it avoids copying code (in this case the check against treshold 60) and the risk of inconsistencies between the two copies. In this case the mistake I introduces would result in a wrong classification of the edge case temperature 60.
Related
So I have an assignment, and within it is a question that requires you to construct a 2D array with 5 rows and 4 columns, with each of them containing grades. The question requires you to determine how many grades are less than 60, between 60 and 70 and so on (till 100). Thing is when I try to search through it, there should only be 20 total grades, but my solution gives some far fetched number like 60,000 or whatever. I'm at a loss as to what is wrong with my code. I used two for loops to search through the array. Attached is what I've tried. Thanks a ton for any help
#include <stdio.h>
int main(){
double grades[5][4] = {
{69, 58, 95, 78},
{84, 75, 86, 32},
{75, 68, 65, 73},
{99, 54, 24, 88},
{65, 78, 84, 65}
};
int lessthan60, sixtyseventy, seventyeighty, eightyninety, greaterthan90;
for (int r = 0; r < 5; r++){
for (int c=0; c < 4; c++){
if (grades[r][c] < 60){
lessthan60++;
}
else if (grades[r][c] >=60 && grades[r][c] < 70){
sixtyseventy++;
}
else if (grades[r][c] >=70 && grades[r][c] < 80){
seventyeighty++;
}
else if (grades[r][c] >=80 && grades[r][c] < 90){
eightyninety++;
}
else{
greaterthan90++;
}
}
}
printf("Grades less than 60: %d\n", lessthan60);
printf("Grades between 60 and 70: %d\n", sixtyseventy);
printf("Grades between 70 and 80: %d\n", seventyeighty);
printf("Grades between 80 and 90: %d\n", eightyninety);
printf("Grades between 90 and 100: %d\n", greaterthan90);
return 0;
}
These variables having automatic storage duration
int lessthan60, sixtyseventy, seventyeighty, eightyninety, greaterthan90;
are uninitialized and have indeterminate values. You have to initialize them by zero explicitly
int lessthan60 = 0, sixtyseventy = 0, seventyeighty = 0, eightyninety = 0, greaterthan90 = 0;
Also if statements can be written simpler like
if (grades[r][c] < 60){
lessthan60++;
}
else if ( grades[r][c] < 70){
sixtyseventy++;
}
else if ( grades[r][c] < 80){
seventyeighty++;
}
else if ( grades[r][c] < 90){
eightyninety++;
}
else{
greaterthan90++;
}
Also instead of the magic numbers 4 and 5 it is better to use named constants as for example
enum { ROWS = 5, COLS = 4 };
double grades[ROWS][COLS] = {
{69, 58, 95, 78},
{84, 75, 86, 32},
{75, 68, 65, 73},
{99, 54, 24, 88},
{65, 78, 84, 65}
};
//...
for (int r = 0; r < ROWS; r++){
for (int c=0; c < COLS; c++){
//...
This way, you are starting with garbage values.
You need to initialize counters lessthan60, sixtyseventy, seventyeighty, eightyninety, greaterthan90 to zero.
I am trying to write a program that needs to check the resistor inputs to see if they are standard values. I have gotten this far, but I am very confused. Any guidance would help. The main program accepts values from 1-1000 as resistor inputs. These inputs must then be compared to the list of standard values, {10, 12, 15, 18, 22, 27, 33, 39, 47, 56, 68, 82}. Any multiple of these values is considered standard such as 8.2, 82, 820.
void checkstdval (float ra, float rb)
{
float stdv[12] = {10, 12, 15, 18, 22, 27, 33, 39, 47, 56, 68, 82};
while(1)
{
while (ra <10)
ra *= 10;
while (ra <= 100)
ra /= 10;
if ((ra - stdv) < 0.01)
break;
else
{
printf("%.2f is not a standard resistor value\n", ra);
break;
}
}
while(1)
{
while (rb <10)
rb *= 10;
while (rb <= 100)
rb /= 10;
if ((rb - stdv) < 0.01)
break;
else
{
printf("%.2f is not a standard resistor value\n", rb);
break;
}
}
From list of collatz sequence that are like 34,17,52,26,13...4,2,1.I want to print 40 characters for each line like "50, 25, 76, 38, 19, 58, 29, 88, 44, 22," will be first line of 40 characters and then next line and should stop when last number are 4, 2, 1
I am unable to stop the program when 4, 2, 1 sequence is encountered.
I have first created the required sequence of numbers. Post that tried to print numbers by for loop with while condition of 1.
int length;
int *ptr;
int i = 50, j = 0;
for (i; i >= 2; )
{
if (i % 2 == 0)
{
i = i / 2;
}
else if (i % 2 != 0)
{
i = (3 * i) + 1;
}
ptr[j] = i;
printf("Total Value: %d, \n", ptr[j]);
j++;
}
for (i = 0; i < 50; )
{
j = 10 + i;
while (i < j)
{
printf("%d, ", ptr[i]);
i++;
if (ptr[i] == 1)
{
break;
}
}
printf("\n");
}
Expected result:
50, 25, 76, 38, 19, 58, 29, 88, 44, 22,
11, 34, 17, 52, 26, 13, 40, 20, 10, 5,
16, 8, 4, 2, 1,
For starters, your code causes a segmentation fault on my machine. You declared ptr as a pointer to an integer int *ptr;, but you are treating it as an array and storing values into it ptr[j] = i;. If you want to put data into an array, then you will either need to malloc a buffer or declare ptr as an array on the stack, i.e., int ptr[SIZE].
A pointer is not a means of storage itself. If you want to have an array for storage, then you need to explicitly allocate an array either on the stack or on the heap.
I want to make a program to get the weighted average (formula = (mark*(credits corresponds to it))/total credits) from the best(highest) 120 credits module from the following marks and credits (the credits corresponds to the module):
module[12]={48, 77, 46, 82, 85, 43, 49, 73, 65, 48, 47, 51}
credits[12]={60, 20, 20, 20, 10, 20, 10, 10, 10, 20, 20, 10}
What I have done is bubble sort the array, so that the array is sorted by decreasing manner to know which marks is higher, as shown below:
module[12]={85, 82, 77, 73, 65, 51, 49, 48, 48, 47, 46, 43}
credits[12]={10, 20, 20, 10, 10, 10, 10, 60, 20, 20, 20, 20}
And then I need to choose the best 120 credits module from the sorted array so that the weighted average will be maximum, but then I have no idea where to start. =(
Someone help me! Thanks a lot!
EDIT:
I have tried to work out the code myself, and eventually get the following code, it works, but for some special case it stop working =(
float credits=0, result=0;
n=0;
struct{
float credits;
float result;
float n;
float addpoint;
}point;
while (credits < 120){
credits+=credits[n];
result+=(result[n]*credits[n]);
n++;
}
if (credits != 120){
credits -= credits[n-1];
result -= (result[n-1]*credits[n-1]);
point.credits = credits;
point.result = result;
point.n = (n-1)-1;
point.addpoint = n;
again: while (credits < 120){
credits+=credits[n];
result+=(result[n]*credits[n]);
n++;
}
if (credits != 120){
point.credits -= credits[point.n-1];
point.result -= result[point.n-1]*credits[point.n-1];
point.n--;
credits = point.credits;
result = point.result;
n = point.addpoint-1;
goto again;
}
}
EDIT:
Solved. Using knapsack problem code/integer linear programming by the application of glpk
The other way, which is practical for small examples like the one you've got, is to use dynamic programming. One can build up a table of "optimal score if you use the first k subjects, and want credits to add up to T". The code's a bit messy because C doesn't make it particularly easy to have dynamically sized 2d arrays, but here's a solution. Probably your professor was expecting something along these lines.
A small note, I divided all the credits (and the target credits of 120) by 10 because the common factor was redundant, but the code works just fine without that (it'll just use a tad more memory and time).
#include <stdio.h>
#include <stdlib.h>
int max(int a, int b) {
return a > b ? a : b;
}
#define GET(t, i, j, n) ((t)[(i) * (n + 1) + j])
// optimize_marks takes arrays creds and marks (both of length n),
// and finds a subset I of 0..(n-1) that maximizes
// sum(i in I)creds[i]*marks[i], such that sum(i in I)creds[i] = total.
void optimize_marks(size_t n, int *creds, int *marks, int total) {
// tbl[k * (total + 1) + T] stores the optimal score using only the
// first k subjects for a total credit score of T.
// tbl[n * (total + 1) + total] will be the final result.
// A score of -1 means that the result is impossible.
int *tbl = malloc((n + 1) * (total + 1) * sizeof(int));
for (int i = 0; i <= n; i++) {
for (int T = 0; T <= total; T++) {
if (i == 0) {
// With 0 subjects, the best score is 0 if 0 credits are
// required. If more than 0 credits are required, the result
// is impossible.
GET(tbl, i, T, total) = -(T > 0);
continue;
}
// One way to get T credits with the first i subjects is to
// get T credits with the first (i-1) subjects.
GET(tbl, i, T, total) = GET(tbl, i - 1, T, total);
// The other way is to use the marks for the i'th subject
// and get the rest of the credits with the first (i-1) subjects.
// We have to check that it's possible to use the first (i-1) subjects
// to get the remainder of the credits.
if (T >= creds[i-1] && GET(tbl, i - 1, T - creds[i-1], total) >= 0) {
// Pick the best of using and not using the i'th subject.
GET(tbl, i, T, total) = max(
GET(tbl, i, T, total),
GET(tbl, i - 1, T - creds[i-1], total) + marks[i-1] * creds[i-1]);
}
}
}
int T = total;
for (int i = n; i > 0; i--) {
if (GET(tbl, i - 1, T, total) < GET(tbl, i, T, total)) {
printf("%d %d %d\n", i, creds[i-1], marks[i-1]);
T -= creds[i-1];
}
}
}
int main(int argc, char *argv[]) {
int creds[] = {6, 2, 2, 2, 1, 2, 1, 1, 1, 2, 2, 1};
int marks[] = {48, 77, 46, 82, 85, 43, 49, 73, 65, 48, 47, 51};
optimize_marks(12, creds, marks, 12);
return 0;
}
The program gives the solution as the ILP program:
12 1 51
11 2 47
10 2 48
9 1 65
8 1 73
5 1 85
4 2 82
2 2 77
This is an integer linear programming problem. You want to find a vector [x1 x2 x3 ... x12] where each of the x's is either 0 or 1, such that sum(x[i] * cred[i]) = 120 and that sum(x[i] * cred[i] * marks[i]) is maximised.
There's a large body of research in how to solve such problems, but there's existing solvers out there and ready for you to use and using them is going to save you a vast amount of time over coding a solver up yourself.
Here's a module file for glpk, a free linear programming and integer linear programming solver. You can run it by installing glpk, saving this to a file then running glpsol -m <filename>
set I := 1..12;
var x{I} binary;
param cred{I};
param marks{I};
maximize s:
sum{i in I}(x[i] * cred[i] * marks[i]);
s.t. totalcreds: sum{i in I}(x[i] * cred[i]) = 120;
solve;
printf {i in I} "%d: %d %d %d\n", i, x[i], cred[i], marks[i];
data;
param cred := 1 60, 2 20, 3 20, 4 20, 5 10, 6 20, 7 10, 8 10, 9 10, 10 20, 11 20, 12 10;
param marks := 1 48, 2 77, 3 46, 4 82, 5 85, 6 43, 7 49, 8 73, 9 65, 10 48, 11 47, 12 51;
end;
The output is this:
1: 0 60 48
2: 1 20 77
3: 0 20 46
4: 1 20 82
5: 1 10 85
6: 0 20 43
7: 0 10 49
8: 1 10 73
9: 1 10 65
10: 1 20 48
11: 1 20 47
12: 1 10 51
That is, you should pick courses 2, 4, 5, 8, 9, 10, 11, 12 (ie: the courses with a '1' by them).
You should probably start by isolating all the combinaisons of credits[] elements whose sum equals 120 and store them before calculating all the means.
It would look like that :
// test for all possible combinaisons :
// [0] + [1] + [2]..., [1] + [0] + [2]...
// starting point on the array : n
while(n < 12){
// if the sum isnt equal to 120 and
// we havent covered all the array yet
if(temp < 120 && i < 12){
// if i is different from the starting point
if(i < 11 && i != n){
i++;
temp += credits[i];
// store i
}
}
if(temp >120 && i < 11){
temp -= credits[i];
// remove i
i++;
}
if(temp == 120){
// starting point ++
n++;
}
}
It's not optimal, but it could work.
I have solved a question that says:
Given a natural number n (1 <= n <= 500000), please output the summation of all its proper divisors.
Definition: A proper divisor of a natural number is the divisor that is strictly less than the number.
e.g. number 20 has 5 proper divisors: 1, 2, 4, 5, 10, and the divisor summation is: 1 + 2 + 4 + 5 + 10 = 22.
Input
An integer stating the number of test cases (equal to about 200000), and that many lines follow, each containing one integer between 1 and 500000 inclusive.
Output
One integer each line: the divisor summation of the integer given respectively.
Example
Sample Input:
3
2
10
20
Sample Output:
1
8
22
My code is as follows:
/* #BEGIN_OF_SOURCE_CODE */
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[])
{
int sum = 0,
cases = 0,
i, j, buff;
scanf("%d", &cases); //Number of tests
int *n;
n = (int*) malloc(cases * sizeof(int)); //Defining array for numbers to be tested///////
for (i = 0; i < cases; i++) {
scanf("%d", &n[i]);
}
for (i = 0; i < cases; i++ ) {
buff = n[i] / 2;
if (n[i] == 1) {
sum = -1;
}
if (!(n[i] & 1)) {
for (j = 2; j < buff; j++) {
if (n[i] % j == 0) {
sum += n[i] / j + j;
buff /= j;
}
}
}
else {
for (j = 3; j < buff; j += 2) {
if (n[i] % j == 0) {
if (n[i] / j == j) { sum += j; break; }
else sum += n[i] / j + j;
}
buff /= j;
}
}
printf("%d\n", ++sum);
sum = 0;
}
return 0;
}
/* #END_OF_SOURCE_CODE */
but it is not fast enough. Any suggestions?
I have updated the code below to terminate sooner. Running it for all integers from 1 to 500,000 takes under half a second on a MacBookPro6,1 (2.66 GHz Intel Core i7), compiled with Apple GCC 4.2.1 with -O3.
It uses the formula for σx(n) in the Properties section of the Wikipedia page for the divisor function. It could be made faster with a list of precalculated primes. (126 are needed to support inputs up to 500,000, and this reduces the time to less than a quarter of a second.) There are also some divisions that can be eliminated, at the expense of cluttering the code slightly.
// Return the least power of a that does not divide x.
static unsigned int LeastPower(unsigned int a, unsigned int x)
{
unsigned int b = a;
while (x % b == 0)
b *= a;
return b;
}
// Return the sum of the proper divisors of x.
static unsigned int SumDivisors(unsigned int x)
{
unsigned int t = x;
unsigned int result = 1;
// Handle two specially.
{
unsigned int p = LeastPower(2, t);
result *= p-1;
t /= p/2;
}
// Handle odd factors.
for (unsigned int i = 3; i*i <= t; i += 2)
{
unsigned int p = LeastPower(i, t);
result *= (p-1) / (i-1);
t /= p/i;
}
// At this point, t must be one or prime.
if (1 < t)
result *= 1+t;
return result - x;
}
You don't have to allocate space. Just do line by line.
For each line, there is an O( n ^ 1/2 ) algorithm.
#include <iostream>
using std::cout; using std::endl; using std::cin;
int main() {
int count, number;
cin >> count;
for (int i = 0; i < count; ++i) {
cin >> number;
int sum = 1;
for ( int j = 2; j * j <= number; ++j ) {
if ( number % j == 0 ) {
sum += j;
sum += number / j;
}
if ( j * j == number ) sum -= j; // recalculate twice
}
cout << sum << endl;
}
}
This is the runtime for 200,000 test case
real 0m55.420s
user 0m0.016s
sys 0m16.124s
I would start by NOT storing the numbers in an array at all. You don't need to - just read the value, process it, and output the result. The compiler may well not realize that n[i] is the same value throughout the loop, and that nothing else modifies it.
The logic doesn't seem very clear to me. And if (n[i] == 1) { sum = 1} else ... would make more sense than setting sum = -1.
You could perhaps also, keep a list of "common factors" (http://en.wikipedia.org/wiki/Memoization), so that you don't have to recalculate the same thing many times over. [If you know that somehing has the factor 24, then it also has 2, 3, 4, 6 and 8, for example.
I replied to a similar question on stackoverflow
There is a faster performing algorithm which is based on a formula for the sum of divisor using the decomposition in prime factors.
First you construct a primetable such that the last prime squared is smaller than the upper bound for your number. Then you apply the formula to each entry. If a number is written as
n = a1^p1 * a1^p2 *... *an^pn
the complexity of finding the sum for a given number n will be
p1+p2+...+pn = roughtly log(n)
which is better than the complexity O(sqrt(n)) of the first optimization which stop the loop early
Let's suppose you have a way to compute primes relatively quickly. This could be a one time upfront activity, bounded by the square root of the largest input value. In this case, you already know the bound of the largest input value (500000), so you can simply hard code a table of primes into the program.
static unsigned P[] = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701
};
static int P_COUNT = sizeof(P)/sizeof(*P);
Now, from the primes, for each input value, you can:
Compute the prime factorization
Compute the product of the sums of the powers of each prime factor.
This will result in the sum of the divisors. Subtract the input value from the sum to obtain the sum of proper divisors. These two steps can be combined into a single loop.
This algorithm works because multiplying polynomials naturally results in sums of all combinations of the polynomial terms multiplied together. In the case where each polynomial term consists of powers of primes that divide the input, the combinations of the terms multiplied together make up the divisors. The algorithm is fast, and should be able to process 500000 numbers in the interval [1, 500000] in less than a second on a Core i3 or better processor.
The following function implements the method described above.
unsigned compute (unsigned n) {
unsigned sum = 1;
unsigned x = n;
for (int i = 0; i < P_COUNT; ++i) {
if (P[i] > x / P[i]) break; /* remaining primes won't divide x */
if (x % P[i] == 0) { /* P[i] is a divisor of n */
unsigned sub = P[i] + 1; /* add in power of P[i] */
x /= P[i]; /* reduce x by P[i] */
while (x % P[i] == 0) { /* while P[i] still divides x */
x /= P[i]; /* reduce x */
sub = sub * P[i] + 1; /* add by another power of P[i] */
}
sum *= sub; /* product of sums */
}
}
if (x > 1) sum *= x + 1; /* if x > 1, then x is prime */
return sum - n;
}
The complexity of this code in O(n * log(n)). But you can output the required answer with constant time.
int ans[500000 + 10], m = 500000;
int f(){
for(int i = 1; i <= m; i++){
for(int j = i + i; j <= m; j += i){
ans[j] += i;
}
}
}
Here ans is an array that contain sum of proper divisor from 2 to m.