排列组合或容斥原理
Posted caijiaming
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排列组合或容斥原理相关的知识,希望对你有一定的参考价值。
题目链接:https://vjudge.net/contest/237052#problem/H
Enough with this Harry Potter, please! What are we, twelve-year olds? Let‘s get our teeth into some real pumpkin pasties -- oops, programming problems!
Here we go!
Let‘s define the diversity of a list of numbers to be the difference between the largest and smallest number in the list.
For example, the diversity of the list (1, -1, 2, 7) = 7 - (-1) = 8.
A substring of a list is considered a non-empty sequence of contiguous numbers from the list. For example, for the list (1,3,7), the substrings are (1), (3), (7), (1,3), (3,7), (1,3,7). A subsequence of a list is defined to be a non-empty sequence of numbers obtained by deleting some elements from the list. For example, for the list (1,3,7), the subsequences are (1), (3), (7), (1,3), (3,7), (1,7), (1,3,7).
Given a list of length N find the number of substrings and subsequences in this list with the maximum diversity. If a substring/subsequence having maximum diversity occurs multiple times in the list, each of its occurences adds towards the answer. And tell Harry Potter your answer
Input (STDIN):
The first line contains T, the number of test cases. Then follow T test case blocks.
Each blocks starts with the first line containing the number N.
The second line contains a list of numbers in this list.
Output (STDOUT):
For each test case, output the number of substrings and the number of subsequences in this list with the maximum diversity.
Since the answers maybe very large, output them modulo 1000000007.
Constraints:
T <= 10
N <= 100,000
Each number in the list is between 1 and 100,000 inclusive.
Sample Input:
3
3
1 2 3
4
1 4 3 4
3
3 2 1
Sample Output:
1 2
3 6
1 2
题目大意:输入t,t组测试数据,输入n,有n个数,判断两个不同的字符串和序列串的标准是最大值减最小值不同,字符串必须是连续的,序列串可以不连续
问你有多少个最大的字符串和序列串
个人思路:因为所求一定是最大值减最小值,所以先把最大值和最小值记录下来。先看字符串怎么求,看下面例子
这是一个公式:sum=sum+min(t1,t2),t1,t2是最小最大值的下标,会有更新,刚开始都赋值为0
2 1 4 3 2 1 min=1,max=4,t1=0,t2=0;
i=1, t1=0,t2=0,sum=min(0,0)+sum=0;
i=2, t1=2,t2=0,sum=min(2,0,)+sum=0;
i=3, t1=2,t2=3,sum=min(2,3)+sum=2,有2 1 4和1 4
i=4, t1=2,t2=3,sum=min(2,3)+sum=4, 有2 1 4 3和1 4 3
i=5, t1=2,t2=3,sum=min(2,3)+sum=6,有2 1 4 3 2和1 4 3 2
i=6, t1=6,t2=3,sum=min(6,3)+sum=9,有2 1 4 3 2 1和1 4 3 2 1 和4 3 2 1
那么我们来看为什么会有这个公式呢,加上本身就不用多说了,那么为什么是加上min(t1,t2)呢,因为从后面每增加一个数,都可以在第一个到min(t1,t2)个数开始到末尾
都是一个字符串,所以增加的就是min(t1,t2)
然后要求序列串,有两种求法,一种是排列组合,还要一种是容斥原理。需要算出有多少个最大值和最小值
假设最大值max_num个,最小值min_num个,总共有n个
排列组合的公式是:(2^min_num-1)*(2^max_num-1)*(2^(n-min_num-max_num)),为什么是这样,自己想一下,就能清楚
容斥原理的公式是:2^n-2^(n-min_num)-2^(n-max_num)+2^(n-min_num-max_num)
还有这题很坑,不能用I64d,原因我也不清楚,检查了很久,把输入输出改一下就过了,气气气·······
看代码
#include<iostream> #include<stdio.h> #include<string.h> #include<cmath> #include<math.h> #include<algorithm> #include<set> typedef long long ll; using namespace std; const ll mod=1e9+7; #define INF 0x3f3f3f ll quickpow(ll a,ll b) { //a的b次方 ll res=a,ans=1; while(b) { if(b&1) { ans=ans*res%mod; res=res*res%mod; } else res=res*res%mod; b=b>>1; } return ans; } int main() { ll t; ll a[100050]; scanf("%lld",&t); //cin>>t; while(t--) { ll n,mi=INF,ma=-1,l=0,r=0,ans=0,ans1=0,min_num=0,max_num=0;//l代表最小值的下标,r代表最大值的下标 scanf("%lld",&n); //cin>>n; for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); // cin>>a[i]; if(a[i]>ma) ma=a[i]; if(a[i]<mi) mi=a[i]; } if(mi==ma) { ans=n*(n+1)/2%mod; ans1=quickpow(2,n)-1; printf("%lld %lld ",ans,ans1); //cout<<ans<<‘ ‘<<ans1<<endl; continue; } for(int i=1;i<=n;i++) { if(a[i]==mi) { l=i; min_num++;//最小值个数 } if(a[i]==ma) { r=i; max_num++;//最大值个数 } ans=(ans+min(l,r))%mod;//子串个数 }//注意这里要时刻%mod,不这样就wa,可能会爆 ans1=(quickpow(2,min_num)-1)%mod*(quickpow(2,max_num)-1)%mod*(quickpow(2,n-min_num-max_num))%mod; // ans1=(quickpow(2,n)-quickpow(2,n-min_num)-quickpow(2,n-max_num)+quickpow(2,n-min_num-max_num))%mod; if(ans1<0) ans1=ans1+mod; printf("%lld %lld ",ans,ans1); //cout<<ans<<‘ ‘<<ans1<<endl; } return 0; }
以上是关于排列组合或容斥原理的主要内容,如果未能解决你的问题,请参考以下文章
[Codeforces 1228E]Another Filling the Grid (排列组合+容斥原理)