• hihocoder1475 数组分拆【DP+前缀和优化】


    思路:

    DP[ i ] 代表以 i 结尾的方案数. dp[i] += sum[i] - sum[j - 1] != 0 ? dp[j] : 0 ;

    对于100%的数据,满足1<=N<=105, |Ai|<=100
    n 1e5呀,两层for,GG;
    利用树状数组维护sum[i],存的是以sum[i]的方案数 ,
    那么每次加上当前所有的方案,减去sum[i]的方案,就好了。
    这里还有一个小问题就是 |sum[i]|<=1e7,所以先离散化一下就好了。
    把当前所有前缀和的方案数加起来。。然后减掉以自己的方案数。

    也可以用map.


    树状数组维护。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const LL mod=1e9+7;
    const int N=1e5+10;
    LL sval[N],sum[N];
    LL dp[N];
    int lowbit(int x)
    {
        return x&(-x);
    }
    LL Sum(int d)
    {
        LL ans=0;
        while(d)
        {
            ans=(ans+sval[d])%mod;
            d=d-lowbit(d);
        }
        return ans;
    }
    
    void add(int d,LL val,int n)
    {
        while(d<=n)
        {
            sval[d]=(sval[d]+val)%mod;
            d+=lowbit(d);
        }
    }
    
    vector<LL>xs;
    int main()
    {
        LL n,a;
        scanf("%lld",&n);
        sum[0]=0;
        xs.push_back(0);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a);
            sum[i]=sum[i-1]+a;
            xs.push_back(sum[i]);
        }
        sort(xs.begin(),xs.end());
        auto it=unique(xs.begin(),xs.end());
        for(int i=0;i<=n;i++)
            sum[i]=lower_bound(xs.begin(),it,sum[i])-xs.begin()+1;
        memset(dp,0,sizeof(dp));
        for(int i=0;i<=n;i++)
        {
            dp[i]+=Sum(xs.size());
            dp[i]-=Sum(sum[i])-Sum(sum[i]-1);
            dp[i]=(dp[i]+mod)%mod;
            if(dp[i]==0)
                dp[i]=1;
            add(sum[i],dp[i],xs.size());
        }
        printf("%lld
    ",dp[n]);
        return 0;
    }
    
    

    map维护

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const LL mod=1e9+7;
    const int N=1e5+10;
    LL sum[N];
    LL dp[N];
    map<int,int>mp;
    
    int main()
    {
        LL n,a;
        scanf("%lld",&n);
        sum[0]=0;
        mp.clear();
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a);
            sum[i]=sum[i-1]+a;
        }
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        mp[0]=1;
        LL cnt=1;
        for(int i=1;i<=n;i++)
        {
            if(!mp.count(sum[i]))
            {
                dp[i]=cnt;
                mp[sum[i]]=dp[i];
            }
            else
            {
                dp[i]=((cnt-mp[sum[i]])%mod+mod)%mod;
                mp[sum[i]]=(mp[sum[i]]+dp[i]+mod)%mod;
            }
            cnt=(cnt+dp[i]+mod)%mod;
        }
        printf("%lld
    ",dp[n]);
        return 0;
    }
    
    


  • 相关阅读:
    zoj 3599 Game 博弈论
    hdu 2486/2580 / poj 3922 A simple stone game 博弈论
    hdu 1517 A Multiplication Game 博弈论
    hdu 4407 Sum 容斥原理
    hdu 4686 Arc of Dream
    hdu 4588 Count The Carries
    hdu 4586 Play the Dice
    C#学习(5)
    C#学习(4)
    C#学习(3)
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777389.html
Copyright © 2020-2023  润新知