Loading

Project 1:A+B

Introduction

Given \(S\) as a collection of \(N\) positive integers that are no more than \(V\). For any given number \(c\), find two integers \(a\) and \(b\) from \(S\), so that \(a+b=c\). There is no difference in order between \(a\) and \(b\).

In order to determine whether the correct result has been obtained, I chose to use the total number of solutions as the output answer.

Algorithm Specification

Algorithm 1

A natural thought is to enumerate all possible sums and then check one by one whether they are equal to \(c\).

There are \(C_N^2\) ways to combine \(N\) numbers in pairs. That means we will obtain \(C_N^2\) sums(there might be retetitions, but this is not important). To achieve this operation, we can use two loops to enumerate all possible scenaiors.

for (i=1->n)
    for (j=i+1->n)
        if (a[i]+a[j] equals c)
            number++;

Algorithm 2

In order to enhance the efficiency of the algorithm, we are considering whether we can reduce one of the loops. When the first loop has determined \(a\),we need to find a suitable \(b\) such that \(a+b=c\). It is easy to see that at this point, \(b\) should be equal to \(c-a\). This means that we might not need to go through every single number to find such a suitable \(b\). All we need to do is check if \(c-a\) is in \(S\). This step does not require a loop; instead, it can be accomplished though a binary search.

Given this idea, our algorithm can be optimized as follows: first, enumerate \(a\), and then perform a binary search to check if \(c-a\) is in \(S\). Note that in order to ensure the correctness of the binary search, we need to sort the array \(S\) beforehand.

To handle the repetition issue, for each \(c-a\), we can determine its leftmost and rightmost positions in the sorted \(S\) to obtain the count of \(c-a\) in \(S\). If \(c-a\) is exactly equal to \(a\), ther we only need to count the number of \(a\), and then use combination formula to obtain the anwser.

sort
for (i=1->n)
{
    if 2*a[i]=c
        then get the number of a[i] and calc answer
    else
    {
        get the leftmost and rightmost position of c-a[i];
        calculate answer
    }
}

Testing Result

Analisis and Comments

Algorithm 1

Since we use two loop to enumerate all possible scenaiors, it is obvious that the time complexity is \(\mathcal O(N^2)\). At the same time,we used a one-dimensional array, which implies that the space complexity is \(\mathcal O(N)\).

Algorithm 2

First, consider the time complexity after sorting. The time complexity of enumerate \(a\) is \(\mathcal O(N)\), and the time complexity of finding \(c-a\) through binary search is \(\mathcal O(\log N)\). Therefore, the overall time complexity of this process is \(\mathcal O(N\log N)\). During this process, if we encounter the situation where \(c-a\) equals \(a\), we will adopt a looping approach to determine the number of \(c/2\). Since this situation occurs at most once, it will not affect our time complexity.

In order to prevent the time complexity of the algorithm from deteriorating, the step of sorting requires the use of some excellent sorting methods, such as quick sort and merge sort. To achieve stability, we have chosen merge sort here, and its time complexity is also \(\mathcal O(N\log N)\).

Since only a one-dimensional array was used as well, the space complexity remains \(\mathcal O(N)\).

Implovement

After sorting, we can use the two-pointer approach to optimize the time complexity of the subsequent operations to \(\mathcal O(N)\). However, this approach is more complicated, and since it also requires soring, there is no much optimization in terms of the overall time complexity of the program.

Timing Table and Graph



Appendix Code

#include<stdio.h>//Algorithm 1(Brute Force)
#define N 100005
int n,v,c,ans,a[N];
int main(void)
{
    scanf("%d%d",&n,&c);
    for (int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    for (int i=1;i<=n;++i)
        for (int j=i+1;j<=n;++j)
            if (a[i]+a[j]==c) ans++;
    printf("%d\n",ans);
    return 0;
}
#include<stdio.h>//Algorithm 2(Sort+Binary Search)
#define N 100005
int n,c,ans,a[N];
void merge(const int *aBegin,const int *aEnd,const int *bBegin,const int *bEnd,int *c) 
{
    while (aBegin!=aEnd&&bBegin!=bEnd) 
    {
        if (*bBegin<*aBegin)
        {
            *c=*bBegin;
            ++bBegin;
        } 
        else 
        {
            *c=*aBegin;
            ++aBegin;
        }
        ++c;
    }
    for (;aBegin!=aEnd;++aBegin,++c) *c=*aBegin;
    for (;bBegin!=bEnd;++bBegin,++c) *c=*bBegin;
}
void mergesort(int *a,int l,int r)
{
    if (r-l<=1) return;
    int mid=l+((r-l)>>1);
    mergesort(a,l,mid);mergesort(a,mid,r);
    int tmp[N]={};
    merge(a+l,a+mid,a+mid,a+r,tmp+l);
    for (int i=l;i<r;++i)
        a[i]=tmp[i];
}
int main(void)
{
    scanf("%d%d",&n,&c);
    for (int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    mergesort(a,1,n+1);//Merge Sort
    for (int i=1;i<=n;++i)// get a
    {
        if (2*a[i]>c) break; 
        if (2*a[i]==c)//to reduce repetition
        {
            int cnt=0;
            for (;i<=n&&2*a[i]==c;++i) cnt++;
            ans+=cnt*(cnt-1)/2;
            break;
        }
        int l=i+1,r=n,lmid=-1,rmid=-1;
        while (l<=r)
        {
            int mid=(l+r)>>1;
            if (a[i]+a[mid]<c) l=mid+1;
            else if (a[i]+a[mid]>c) r=mid-1;
            else lmid=mid,r=mid-1;
        }//binary sort to get the leftmost one c-a
        l=i+1;r=n;
        while (l<=r)
        {
            int mid=(l+r)>>1;
            if (a[i]+a[mid]<c) l=mid+1;
            else if (a[i]+a[mid]>c) r=mid-1;
            else rmid=mid,l=mid+1;
        }//binary sort to get the right most one c-a
        if (~lmid) ans+=rmid-lmid+1;//get the total number of c-a
    }
    printf("%d\n",ans);
    return 0;
}

Declaration

I hereby declare that all the work done in this project titled Thunder_S is of my indepedent effort.

posted @ 2026-04-05 15:12  Thunder_S  阅读(1)  评论(0)    收藏  举报