• UVALive 5990 Array Diversit


    题意:对于一个数列A,substring是一个连续子串,subsequence是其非连续子序列。对于一个数字序列,记它的diversity是它的最大元素减去最小元素的差。给出一个数字序列,求与它diversity相同的substring和subsequence各有多少个。比如若A为1,4,3,4,则答案为3和6。

    解法:组合数学问题。首先,记A中最大元素为ma,最小元素为mi,且最大元素有s1个,最小元素有s2个,数列A长度为n。

       则A的所有subsequence共有2^n个,不含ma的subsequence有2^(n-s1)个,不含mi的subsequence有2^(n-s2)个,mi和ma都不含的有2^(n-s1-s2)个,由容斥原理,所求为2^n - 2^(n-s1) - 2^(n-s2) + 2^(n-s1-s2)个。

       对于substring的个数,选取的的substring为A[begin] 到 A[end],枚举end从0到n-1,并且用t1记录目前位置最后出现的mi的位置,t2记录目前最后出现的ma的位置,则对于每个枚举的end,ans += min(t1, t2)。详见代码。

    比赛的时候没有想清楚,substring个数的求法写得好复杂。。。后来看了男神代码自己默默模仿了一份。。。。

    tag:组合数学,counting

     1 /*
     2  * Author:  Plumrain
     3  * Created Time:  2013-12-03 19:43
     4  * File Name: math-LA-5990.cpp
     5  */
     6 #include <iostream>
     7 #include <cstdio>
     8 #include <algorithm>
     9 
    10 using namespace std;
    11 
    12 typedef long long int64;
    13 const int64 mod = 1000000007;
    14 const int N = 100005;
    15 
    16 int64 g[N], a[N];
    17 int64 min(int64 a, int64 b) {return a > b ? b : a;}
    18 int64 max(int64 a, int64 b) {return a > b ? a : b;}
    19 
    20 int main()
    21 {
    22     g[0] = 1;
    23     for (int i = 1; i < N; ++ i)
    24         g[i] = g[i-1] * 2 % mod;
    25     
    26     int T, n;
    27     scanf ("%d", &T);
    28     while (T--){
    29         int64 mi = mod, ma = 1;
    30         scanf ("%d", &n);
    31         for (int i = 0; i < n; ++ i){
    32             scanf ("%lld", &a[i]);
    33             mi = min(mi, a[i]);
    34             ma = max(ma, a[i]);
    35         }
    36 
    37         int64 ans1 = 0, ans2 = 0;
    38 
    39         if (mi == ma){
    40             ans1 = ((int64)(n + 1) * n / 2) % mod;
    41             ans2 = g[n] - 1;
    42             printf ("%lld %lld
    ", ans1, ans2);
    43             continue;
    44         }
    45 
    46         int t1 = -1, t2 = -1, s1 = 0, s2 = 0;
    47         for (int i = 0; i < n; ++ i){
    48             if (a[i] == mi){
    49                 ++ s1; t1 = i;
    50             }
    51             if (a[i] == ma){
    52                 ++ s2; t2 = i;
    53             }
    54 
    55             ans1 = (ans1 + min(t1+1, t2+1)) % mod;
    56         }
    57 
    58         ans2 = (g[n] - g[n-s1] - g[n-s2] + g[n-s1-s2]) % mod;
    59         if (ans2 < 0) ans2 += mod;
    60         printf ("%lld %lld
    ", ans1, ans2);
    61     }
    62     return 0;
    63 }
    View Code
    ------------------------------------------------------------------
    现在的你,在干什么呢?
    你是不是还记得,你说你想成为岩哥那样的人。
  • 相关阅读:
    day2流程控制
    day1初识java
    SVG路径PATH
    Android开发 ---Media
    Android开发 ---ContentProvider数据提供者,Activity和Service就是上下文对象,短信监听器,内容观察者
    Android开发 ---ORMLite实现数据的增删改查,单例模式,Dao栈
    Android开发 ---SQLite数据库,lock文件,结果集游标,适配器,安全退出,给连接设置下划线,编辑器,投影,ContentValues存储,DbHelper,activity栈
    Android开发 ---多线程操作:Handler对象,消息队列,异步任务下载
    深入理解之 Android Handler
    Android开发 ---xml构建选项菜单、上下文菜单(长按显示菜单)、发通知、发送下载通知
  • 原文地址:https://www.cnblogs.com/plumrain/p/LA_5990.html
Copyright © 2020-2023  润新知