题意:给定一个序列,让你求两种数,一个是求一个子序列,包含最大值和最小值,再就是求一个子集包含最大值和最小值。

析:求子序列,从前往记录一下最大值和最小值的位置,然后从前往后扫一遍,每个位置求一下数目就好。

求子集可以用排列组合解决,很简单,假设最大值个数是 n,最小值的数是 m,总数是 N,答案就是 (2^n-1) * (2^m-1)*2^(N-m-n),

当然要特殊判断最大值和最小值相等的时候。

当然也可以用容斥来求,就是总数 - 不是最大值的数目 - 不是最小值的数目 + 不是最大值也不是最小值的数目,其实也差不多

代码如下:

排列组合:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e17;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1e5 + 10;
const int mod = 1000000007;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
} LL fast_pow(int n){
LL a = 2, ans = 1;
while(n){
if(n & 1) ans = ans * a % mod;
n >>= 1;
a = a * a % mod;
}
return ans;
} int a[maxn];
vector<int> v1, v2; int main(){
int T; cin >> T;
while(T--){
scanf("%d", &n);
int mmin = mod, mmax = 0;
for(int i = 0; i < n; ++i){
scanf("%d", a+i);
mmin = min(mmin, a[i]);
mmax = max(mmax, a[i]);
}
v1.clear(); v2.clear();
for(int i = 0; i < n; ++i)
if(mmin == a[i]) v1.push_back(i);
else if(mmax == a[i]) v2.push_back(i);
if(v1.size() == n){
LL ans1 = (LL)n * (n+1) / 2 % mod;
LL ans2 = (fast_pow(n) - 1 % mod) % mod;
printf("%lld %lld\n", ans1, ans2);
continue;
}
LL ans2 = (fast_pow(v1.size())-1) * (fast_pow(v2.size())-1) % mod * fast_pow(n-v1.size()-v2.size()) % mod;
ans2 = (ans2 + mod) % mod;
int i = 0, j = 0, pre = 0;
LL ans1 = 0;
while(true){
int t1 = min(v1[i], v2[j]);
int t2 = max(v1[i], v2[j]);
ans1 = (ans1 + (LL)(t1-pre+1) * (n-t2)) % mod;
v1[i] < v2[j] ? ++i : ++j;
if(i == v1.size() || v2.size() == j) break;
pre = min(t1+1, min(v1[i], v2[j]));
}
printf("%lld %lld\n", ans1, ans2);
}
return 0;
}

  

容斥:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e17;
const double inf = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1e5 + 10;
const int mod = 1000000007;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c){
return r >= 0 && r < n && c >= 0 && c < m;
} LL fast_pow(int n){
LL a = 2, ans = 1;
while(n){
if(n & 1) ans = ans * a % mod;
n >>= 1;
a = a * a % mod;
}
return ans;
} int a[maxn];
vector<int> v1, v2; int main(){
int T; cin >> T;
while(T--){
scanf("%d", &n);
int mmin = mod, mmax = 0;
for(int i = 0; i < n; ++i){
scanf("%d", a+i);
mmin = min(mmin, a[i]);
mmax = max(mmax, a[i]);
}
v1.clear(); v2.clear();
for(int i = 0; i < n; ++i)
if(mmin == a[i]) v1.push_back(i);
else if(mmax == a[i]) v2.push_back(i);
if(v1.size() == n){
LL ans1 = (LL)n * (n+1) / 2 % mod;
LL ans2 = (fast_pow(n) - 1 % mod) % mod;
printf("%lld %lld\n", ans1, ans2);
continue;
}
LL ans2 = fast_pow(n);
ans2 = (ans2 - fast_pow(n-v1.size()) - fast_pow(n-v2.size()) + fast_pow(n-v1.size()-v2.size())) % mod;
ans2 = (ans2 % mod + mod) % mod;
int i = 0, j = 0, pre = 0;
LL ans1 = 0;
while(true){
int t1 = min(v1[i], v2[j]);
int t2 = max(v1[i], v2[j]);
ans1 = (ans1 + (LL)(t1-pre+1) * (n-t2)) % mod;
v1[i] < v2[j] ? ++i : ++j;
if(i == v1.size() || v2.size() == j) break;
pre = min(t1+1, min(v1[i], v2[j]));
}
printf("%lld %lld\n", ans1, ans2);
}
return 0;
}

  

SPOJ - AMR11H Array Diversity (水题排列组合或容斥)的更多相关文章

  1. SPOJ - AMR11H Array Diversity (排列组合)

    题意:给定n个数,求包含最大值和最小值的子集(数字连续)和子序列(数字不连续)的个数. 分析: 1.如果n个数都相同,则子集个数为N * (N + 1) / 2,子序列个数为2N-1. 2.将序列从头 ...

  2. SPOJ 3693 Maximum Sum(水题,记录区间第一大和第二大数)

    #include <iostream> #include <stdio.h> #include <algorithm> #define lson rt<< ...

  3. 2018 湖南网络比赛题 HDU - 6286 (容斥)

    题意:不说了. 更加偏向于数学不好的小可爱来理解的. 这篇博客更加偏重于容斥的讲解.用最直观的数学方法介绍这个题. 思路: 在a<=x<=b. c<=y<=d 中满足  x*y ...

  4. 【BZOJ4927】第一题 双指针+DP(容斥?)

    [BZOJ4927]第一题 Description 给定n根直的木棍,要从中选出6根木棍,满足:能用这6根木棍拼 出一个正方形.注意木棍不能弯折.问方案数. 正方形:四条边都相等.四个角都是直角的四边 ...

  5. 【HDU 5532 Almost Sorted Array】水题,模拟

    给出一个序列(长度>=2),问去掉一个元素后是否能成为单调不降序列或单调不增序列. 对任一序列,先假设其可改造为单调不降序列,若成立则输出YES,不成立再假设其可改造为单调不增序列,若成立则输出 ...

  6. Eugeny and Array(水题,注意题目描述即可)

    Eugeny has array a = a1, a2, ..., an, consisting of n integers. Each integer ai equals to -1, or to ...

  7. Educational Codeforces Round 69 (Rated for Div. 2) C. Array Splitting 水题

    C. Array Splitting You are given a sorted array

  8. Distinct Substrings SPOJ - DISUBSTR(后缀数组水题)

    求不重复的子串个数 用所有的减去height就好了 推出来的... #include <iostream> #include <cstdio> #include <sst ...

  9. [CTS2019]珍珠(NTT+生成函数+组合计数+容斥)

    这题72分做法挺显然的(也是我VP的分): 对于n,D<=5000的数据,可以记录f[i][j]表示到第i次随机有j个数字未匹配的方案,直接O(nD)的DP转移即可. 对于D<=300的数 ...

随机推荐

  1. 《Javascript高级程序设计》阅读记录(四):第五章 下

    这个系列,我会把阅读<Javascript高级程序设计>之后,感觉讲的比较深入,而且实际使用价值较大的内容记录下来,并且注释上我的一些想法.做这个一方面是提升了我的阅读效果以及方便我以后阅 ...

  2. 前端项目使用module.exports文件一定要Webpack编译吗?请问gulp可以编译这种文件吗

    import引入类似这种文件,一定要用webpack去编译吗 module.pxports 是CMD规范的一个全局函数,功能是当前模块对外提供接口.require可以直接使用这个接口.例子: echo ...

  3. 推荐几本学习MySQL的好书

    转载:http://mingxinglai.com/cn/2015/12/material-of-mysql/ 我这里推荐几本MySQL的好书,应该能够有效避免学习MySQL的弯路,并且达到一个不错的 ...

  4. 8、Selenium+python安装HTMLTestRunner插件

    1.打开网址:http://tungwaiyip.info/software/HTMLTestRunner.html,下载HTMLTestRunner.py 2.copy其HTMLTestRunner ...

  5. boost的asio接收单路大数据量udp包的方法

    开发windows客户端接收RTP视频流,当h264视频达到1080P 60fps的时候,按包来调用recvfrom的函数压力比较大,存在丢包的问题,windows的完成端口的性能效果当然可以解决这个 ...

  6. HDU 2544 最短路(邻接表+优先队列+dijstra优化模版)

    最短路 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  7. Java-API:java.util百科

    ylbtech-Java-API:java.util百科 包含集合框架.遗留的 collection 类.事件模型.日期和时间设施.国际化和各种实用工具类(字符串标记生成器.随机数生成器和位数组.日期 ...

  8. Mongodb 分片与副本集

    测试搭建192.168.3.110mongos 30000,30001,30002config 40000,40001,40002shard1 50001,50002,50003shard2 5000 ...

  9. JavaScript基本概念A

    简介 如果需要了解这些概念, 您应该熟悉 JS 的基本知识. 弱类型 在也无需绞尽脑汁觉得到底采用 float.double,int 还是 short 或是 long 还是 String.只需这样定义 ...

  10. Shell编程进阶 1.3data命令

    date命令是显示日期时间的命令 date 2016年 01月 01日 星期五 15:05:01 CST 修改时间的选项是 -s date -s "2016-01-01 12:56:10&q ...