• *hiho 1475


    题目链接

    描述

    小Ho得到了一个数组作为他的新年礼物,他非常喜欢这个数组!

    在仔细研究了几天之后,小Ho成功的将这个数组拆成了若干段,并且每段的和都不为0!

    现在小Ho希望知道,这样的拆分方法一共有多少种?

    两种拆分方法被视作不同,当且仅当数组断开的所有位置组成的集合不同。

    输入

    每组输入的第一行为一个正整数N,表示这个数组的长度

    第二行为N个整数A1~AN,描述小Ho收到的这个数组

    对于40%的数据,满足1<=N<=10

    对于100%的数据,满足1<=N<=105, |Ai|<=100

    输出

    对于每组输入,输出一行Ans,表示拆分方案的数量除以(109+7)的余数。

    -----------------------------------------------------------------------------------------------------------

    容易想到一个N^2的解法:

    F[i] = Sum(F[0<=j<i])+(pre[i]!=0),pre[j]!=pre[i]. 其中pre[i]为前缀和。

    因为N为10w,所以肯定过不了。

    我们可以先不判断pre[j]是否等于pre[i],即维护一个累加和,然后再减去前缀和等于pre[i]的累加和:F[i] = 当前累加和 - pre[i]的累加和。

    pre[i]的累加和用map维护,是logN的复杂度。

    这样就由N^2降到了NlogN

    #include <map>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int MOD = 1e9+7;
    const int N = 100100;
    int sum[N];
    long long dp[N];
    int main(){
        long long pre = 0;
        map<long,long> records;
        int n; cin>>n; for(int i=0;i<n;i++){
            scanf("%d",sum+i); if(i) sum[i]+=sum[i-1];
            dp[i] = sum[i]?((pre+1)%MOD):pre;
            auto iter = records.find(sum[i]);
            if(iter==records.end()) records[sum[i]]=dp[i];
            else {
                dp[i] = (dp[i]-iter->second+MOD)%MOD;
                iter->second = (iter->second+dp[i])%MOD;
            }
            pre = (pre+dp[i])%MOD;
        }
        printf("%lld
    ",dp[n-1]);
        return 0;
    }
  • 相关阅读:
    文件系统操作与磁盘管理
    文件打包与压缩
    环境变量与文件查找
    Linux 目录结构及文件基本操作
    用户及文件权限管理
    基本概念及操作
    iOS 一个简单的单例
    Xcode编译Undefined symbols for architecture xxx 错误总结
    iOS 直播
    iOS8.1 编译ffmpeg和集成第三方实现直播(监控类)
  • 原文地址:https://www.cnblogs.com/redips-l/p/7811225.html
Copyright © 2020-2023  润新知