• SPOJ


    题意:给定n个数,求包含最大值和最小值的子集(数字连续)和子序列(数字不连续)的个数。

    分析:

    1、如果n个数都相同,则子集个数为N * (N + 1) / 2,子序列个数为2N-1。

    2、将序列从头到尾扫一遍,每当找到一个最大值和最小值的位置maxid,minid,就以这两个位置的区间为基准,计算集合数。

    例如:3 1 4 3 1

    当i=2时,此时maxid=2,minid=1,因此由最大值和最小值---1和4能形成两个子集:3 1 4 和 1 4,即min(minid + 1, maxid + 1)个

    当i=3时,此时maxid=2,minid=1,因此由最大值和最小值---1和4继续扩展,又能形成两个子集:3 1 4 3 和 1 4 3,

    当i=4时,此时maxid=2,minid=4,因此由新的最大值和最小值---1和4继续扩展,又能形成三个子集:3 1 4 3 1 ,1 4 3 1,4 3 1。

    3、记录序列中最大值和最小值的个数,分别为maxnum,minnum。

    子序列个数为,只由最小值形成的集合数a*只由最大值形成的集合数b*不是最小值和最大值的数形成的集合数c

    因为子序列中必须有最大值和最小值,因此a和b不能为空集,所以a=2minnum-1,b=2maxnum-1。

    而c可以为空集,所以c=2n-minnum-maxnum

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<cmath>
    #include<iostream>
    #include<sstream>
    #include<iterator>
    #include<algorithm>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    #include<deque>
    #include<queue>
    #include<list>
    #define lowbit(x) (x & (-x))
    const double eps = 1e-9;
    inline int dcmp(double a, double b){
        if(fabs(a - b) < eps) return 0;
        return a > b ? 1 : -1;
    }
    typedef long long LL;
    typedef unsigned long long ULL;
    const int INT_INF = 0x3f3f3f3f;
    const int INT_M_INF = 0x7f7f7f7f;
    const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
    const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
    const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
    const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
    const LL MOD = 1000000007;
    const double pi = acos(-1.0);
    const int MAXN = 100000 + 10;
    const int MAXT = 1000 + 10;
    using namespace std;
    LL a[MAXN];
    LL POW[MAXN];
    void init(){
        POW[0] = 1;
        for(int i = 1; i < MAXN; ++i){
            POW[i] = (POW[i - 1] * 2) % MOD;
        }
    }
    int main(){
        init();
        int T;
        scanf("%d", &T);
        while(T--){
            int N;
            scanf("%d", &N);
            LL _min = LL_INF;
            LL _max = 0;
            for(int i = 0; i < N; ++i){
                scanf("%lld", &a[i]);
                _max = max(_max, a[i]);
                _min = min(_min, a[i]);
            }
            if(_max == _min){
                LL sum1 = N * (N + 1) / 2;
                LL sum2 = POW[N] - 1;
                printf("%lld %lld
    ", sum1, sum2);
                continue;
            }
            int maxnum = 0;
            int minnum = 0;
            int minid = -1, maxid = -1;
            LL sum1 = 0;
            for(int i = 0; i < N; ++i){
                if(a[i] == _min){
                    minid = i;
                    ++minnum;
                }
                if(a[i] == _max){
                    maxid = i;
                    ++maxnum;
                }
                (sum1 += min(minid + 1, maxid + 1)) %= MOD;
            }
            LL sum2 = ((((POW[minnum] - 1) * (POW[maxnum] - 1)) % MOD) * (POW[N - minnum - maxnum])) % MOD;
            printf("%lld %lld
    ", sum1, sum2);
        }
        return 0;
    }
    

      

  • 相关阅读:
    Project项目视图
    Console(控制台视图)
    Layout布局列表
    Layers层列表
    帐户下拉
    TransformGizmo(变换)切换
    Play播放控件
    变换工具
    工具栏
    Help帮助
  • 原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/7246290.html
Copyright © 2020-2023  润新知