We consider a set of N natural numbers, with values Vi, 1<=i<=N, and two numbers C1 and C2. The problem is to obtain the number of subsets of the N numbers whose sum is between C1 and C2. There can be repeated numbers in V.
A number of problems is solved. For each problem the function to parallelize has:
Input parameters:
-int N: number of natural numbers
-int *V: a vector with the values of the numbers
-int C1: the minimum bound for the value for the sums of numbers
-int C2: the maximum bound
3
5 1 4 9 10 15
30 2 4 41 30 1550
29 3 5 65 80 1670
/* CPP_CONTEST=2018Qual CPP_PROBLEM=F CPP_LANG=CPP+OPENMP CPP_PROCESSES_PER_NODE=1 CPP_NUM_NODES=1 */ #include <stdlib.h> #include <stdio.h> #include <omp.h> #include <iostream> #include <iomanip> #include <math.h> using namespace std; int back(int N,int *V,bool *obtained,int num,int sum,int C1,int C2) { int numsums=0; //for the number of sums for(int i=num+1;i<N;i++) //the number to be included in the set. Only numbers after number i { if(!obtained[sum+V[i]] and C1<=sum+V[i] and sum+V[i]<=C2) //if the number is in the range { obtained[sum+V[i]]=true; numsums++; #ifdef DEBUG cout << "obtained with sum: "<<sum<< " and value "<<V[i]<<endl; #endif } numsums+=back(N,V,obtained,i,sum+V[i],C1,C2); //the remaining elements are those after number i. Parameters i and V[i] correspond to the number and the accumulated sum } return numsums; } int sec(int N,int *V,int C1,int C2) { int numsums=0; //for the total number of sums bool *obtained=(bool *) calloc(sizeof(bool),C2); //stores the values obtained as sum of a subset of the natural numbers for(int i=0;i<N;i++) //the first number included in the set { if(!obtained[V[i]] and C1<=V[i] and V[i]<=C2) //if the number is in the range { obtained[V[i]]=true; numsums++; #ifdef DEBUG cout << "obtained with sum: 0 , and value "<<V[i]<<endl; #endif } numsums+=back(N,V,obtained,i,V[i],C1,C2); //the remaining elements are those after number i. Parameters i and V[i] correspond to the number and the accumulated sum } free(obtained); return numsums; }
esquema-cuda.cu (non modifiable, used by mooshak for in/out and evaluation, provided for local experimentation)
#include <stdlib.h> #include <stdio.h> #include <sys/time.h> #include <omp.h> #include <signal.h> #include <unistd.h> #include <iostream> #include <iomanip> using namespace std; // Scheme for the problem of Sums between two values - CUDA version // Qualification contest for the Spanish Parallel Programming Contest 2018, problem F //initialize a vector void inicialize(int n,int *m,int lv,int uv) { for(int i=0;i<n;i++) m[i]=int(((1.*rand())/RAND_MAX)*(uv-lv)+lv); } //write a matrix, only for debug void escribir(int n,int m,int *a){ for (int i = 0; i < n; i++) { for(int j=0;j<m;j++) cout << a[i*m+j]<<" "; cout <<endl; } cout <<endl; } /* c c mseconds - returns elapsed milliseconds since Jan 1st, 1970. c */ long long mseconds(){ struct timeval t; gettimeofday(&t, NULL); return t.tv_sec*1000 + t.tv_usec/1000; } //abort with the maximum execution time is reached static void alarm_handler(int sig) { fprintf(stderr, "Time Limit Exceeded\n"); abort(); } //the external function to be parallelized by the contestants extern int sec(int,int *,int,int); int main(int argc,char *argv[]) { int num_problems; //number of problems int N; //number of natural numbers int *V; //values of the numbers int seed; //seed for random generation int lower_value; //lower bound for the values in the vector int upper_value; //upper bound for the values in the vector int C1,C2; //interval for the number of sums long long ti,tf,tt=0; //initial, final and total times FILE *stats_file = fopen("stats", "w"); //to stablish a time limit struct sigaction sact; sigemptyset(&sact.sa_mask); sact.sa_flags = 0; sact.sa_handler = alarm_handler; sigaction(SIGALRM, &sact, NULL); alarm(100); /* time limit */ // MPI_Init(&argc,&argv); // MPI_Comm_size(MPI_COMM_WORLD,&np); // MPI_Comm_rank(MPI_COMM_WORLD,&nodo); // The number of test cases is read // and sent to all the processes // if(nodo==0) // { cin >> num_problems; // MPI_Bcast(&cuantos,1,MPI_INT,0,MPI_COMM_WORLD); // } // else // { // MPI_Bcast(&cuantos,1,MPI_INT,0,MPI_COMM_WORLD); // } for(int i=0;i<num_problems;i++) { // if(nodo==0) // { cin >>N; // The first argument is the size of the vector cin >>seed; //seed for the random generation of data to generate cin >>lower_value; //lower bound for the values in the vector cin >>upper_value; //upper bound for the values in the vector cin >> C1 >> C2; // Space for the data V = new int[N]; inicialize(N,V,lower_value,upper_value); srand(seed); #ifdef DEBUG // While debugging the vector written escribir(1,N,V); #endif // } // MPI_Barrier(MPI_COMM_WORLD); ti=mseconds(); int result=sec(N,V,C1,C2); // MPI_Barrier(MPI_COMM_WORLD); tf=mseconds(); // if(nodo==0) // { // The time of the first input is not considered if(i!=0) tt+=tf-ti; #ifdef DEBUG // While debugging the time of each execution is written fprintf(stats_file, "%Ld\n", tf-ti); #endif // The results of each problem are written, // even for the first problem cout <<result<<endl; delete[] V; // } */ } // if(nodo==0) // { fprintf(stats_file, "%Ld\n", tt); fclose(stats_file); // } // MPI_Finalize(); return 0; }