FJUT ACM 2133 第七集,奇思妙想

第七集,奇思妙想

TimeLimit:2000MS  MemoryLimit:128MB
64-bit integer IO format:%lld
 
Problem Description

在经过一个比赛的小插曲后,小A不仅得到主办方的赏识后,还捞到了一大笔钱。有了足够的钱后,他继续出发前往那个聚会城市。由于小A和小C每天都需要赶路,他们需要多买一些舒适的袜子。在离开这个城市前,他先逛了一家袜子批发商店,该商店将不同数量的袜子放入一个个盒子中,且将盒子排成一排,小A看到这样的情景,顿时好奇(程序员的本能):

若把这些箱子围成一个圈,并且拿走一段连续的箱子,且箱子中的袜子的总数量正好等于小A要买的袜子的数量M,有多少种拿法?(假设有N个盒子,盒子编号1-N)

同在小A和小C买完了袜子之后,继续朝着聚会城市出发…

Input

有多组测试案例,

每组测试案例,第一行输入一个正整数N,M(1<=N<=10^6, 1<=M<=10^8),表示有N个箱子。

第二行输入N个非负整数Ai(1<=Ai<=100)、分别表示连续箱子里面的袜子的数量、

Output

对于每组测试案例,输出有多少种方法、

SampleInput
2 1
1 1
3 2
1 1 1
3 3
1 1 1
3 1
1 1 1
3 5
1 1 1
SampleOutput
2
3
1
3
0
【思路】:
看到这一题我的第一直觉是暴力,枚举每个点的情况,这是会有一种情况,需要考虑即 。。。。,n-1,0,。。。。就是越过起点这种情况
我就想到了,先写个判断,因为范围的最大就是一圈,如果一圈的累加得到的sum<M,那么就输出0,==的话就输出1;
如果大于再考虑接下来的情况。就是考虑跨越起点的情况,即内层循环跨越n-1到达n的时候,将n变化成0;
然后我还考虑了跑得时候,不能就是内层遍历的坐标不能大于外层坐标;就是不能重合,附上代码:
#include<stdio.h>
int x[1000005];
int main()
{
    int n,m,i,sum,flag,j,sum2;
    while(~scanf("%d%d",&n,&m))
    {
        flag=0;sum2=0;
        for(i=0; i<n; i++)
            {scanf("%d",&x[i]);
            sum2+=x[i];}
        for(i=0; i<n; i++)
        {if(sum2<m)
        {
            break;
        }
            if(sum2==m)
        {
            flag++;
            break;
        }
            sum=0;
            j=i;
            sum+=x[j];
            j++;
            if(j==n)j=0;
            if(sum>m)continue;
            if(sum==m)
            {
                flag++;
                continue;
            }
            while(j!=i)
            {
                sum+=x[j];
                j++;
                if(j==n)j=0;
                if(sum>m)break;
                if(sum==m)
                {
                    flag++;
                    break;
                }
            }
        }
        printf("%d
",flag);
    }
}

然后跑了下样例,发现正确,直接提交。。。。。

。。。。。。。超时。。。。。。。。

后来仔细一看o(n*n)的复杂度,果然凉凉,就问了下CWL学长,CWL学长说要将复杂度降为o(n)

才能过!

然后发现这题的知识点是双指针,然后发现这个是区间和

附上网站http://blog.csdn.net/linyunzju/article/details/7829073

然后更正了思路,就是两个”指针“在跑,一个在前一个在后,如果值不够,即前方指针++;如果超过,即后面指针++;

但是这题还是要魔改一下,让其可以跑过n值。

其他跟第一个思路相似;

附上代码:

#include<stdio.h>
int x[1000005];
int main()
{
    int n,m,i,l,r,Sum,sum,flag,a;
    while(~scanf("%d%d",&n,&m))
    {
        Sum=0;
        for(i=0; i<n; i++)
        {
            scanf("%d",&x[i]);
            Sum+=x[i];
        }
        l=0;
        r=0;
        a=0;
        flag=0;
        if(Sum==m)printf("1
");
        if(Sum<m)printf("0
");
        if(Sum>m)
        {
            sum=x[l];
            while(l!=n)
            {

                if(sum<m)
                {
                    r++;
                    if(r==n)
                    {
                        r=0;
                    }
                    sum+=x[r];
                }
                if(sum==m)
                {
                    flag++;
                    r++;
                    if(r==n)
                    {
                        r=0;
                    }
                    sum+=x[r];
                }
                if(sum>m)
                {
                    l++;
                    sum=sum-x[l-1];
                }
            }
            printf("%d
",flag);
        }
    }
    return 0;
}

 然后一发ac。

原文地址:https://www.cnblogs.com/qq136155330/p/8137746.html