CF18C Stripe

https://www.luogu.com.cn/problem/CF18C
涉及知识点:模拟,枚举,前缀和
黄色题
思路:看到要求出所有的方案,就想到能切割的点不止一个。这时,就可以通过枚举切割点,进而得到全部分割的可能方案,然后判断十分合法。最后统计出合法方案的数量即可。
 

代码:
#include <iostream>
using namespace std;
const int MAXN=100005;
//题目中数组最大限制
int N;
long long a[MAXN]={0};
long long s[MAXN]={0};
//前缀和数组
long long sum=0;
//所有数的和,其实这个也可以用s[N]代替
int ans=0;
//记录答案
int main()
{
    cin>>N;
    for(int i=1;i<=N;i++) //要从1开始循环,不然会数组溢出
    {
        cin>>a[i];
        s[i]=s[i-1]+a[i];
        //处理前缀和,即将上一个数的前缀和加上目前的数
        sum+=a[i];
        //加和
            //cout<<s[i]<<" ";
        //调试用品,没有什么用
    }
    for(int i=1;i<N;i++)
    {
        if(s[i]*2==sum)
        {
               //这里使用if(sum/s[i]==2)会炸
            //判断是否符合条件
            ans++;
            //如果符合条件,就将ans++
        }
    }
    cout<<ans;
    //输出
    return 0;
    //回家领糖吃咯
}

 

方法2:动态求和

#include<cstdio>
using namespace std;
const int N=1e5+50;
int a[N];
int n;//定义数组,废话

int tot2;
int tot1;//定义存储当前前段数列和与后段数列和的变量

int ans=0;//定义储存答案的变量

int main()
{
    scanf("%d",&n);
    
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(i>1)
        {
           tot2+=a[i];//将1以后的数都加进tot2里面,作为第一个后段数列。
        }
    }
    
    if(n==1)
    {
        printf("0");
        return 0;
    }
    tot1+=a[1];//将a[1]加进tot1里面,作为第一个前段数列。
    
    if(tot1==tot2)//得预先判断第一个前段数列与后段数列是否相等,不判断会很精彩
    {
        ans++;
    }
    
    for(int i=2;i<=n-1;i++)//判断过了第一个,那就从第2个开始
    {
        tot1+=a[i];//每次循环tot1加上a[i],以获得当前前段数列的和
        tot2-=a[i];//每次循环tot2减去a[i],已获得当前后段数列的和
        
        if(tot1==tot2)//如果两者相等
        {
            ans++;//累加
        }
    }
    printf("%d",ans);//完美输出~
    return 0;
}

 

 

posted @ 2022-07-13 15:14  -イレイナ  阅读(30)  评论(0)    收藏  举报