SPOJ - AMR11H
Posted wwq-19990526
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPOJ - AMR11H相关的知识,希望对你有一定的参考价值。
题目链接:https://vjudge.net/problem/26260/origin
题目大意:给出一个数串,定义数串的多样性值为数串中的最值差;又定义两种数串:连续子串和随机子串。
求所有的连续子串和随机子串中多样性值与母串相等的个数。
思路:一个母串,其连续子串的总数为(1+n)*n/2;随机子串的总数为2^n-1;连续子串的多样性值相等数可以通过一个遍历和一个递加等式求出,这等式等下给出详细解释(感觉很神奇)。而随机子串的多样性值相等数=总数-没有最小值的随机子串数-没有最大值的随机子串数+既没有最大值也没有最小值的子串数。(可以画图自行证明,有个博客说是容斥原理),其中有个最大值和最小值相等的情况,要做特殊处理。
以下为ac代码:
1 #include<iostream> 2 #define mod 1000000007 3 using namespace std; 4 int max(int a,int b){ return a>b?a:b; } 5 int min(int a,int b){ return a>b?b:a; } 6 int num[100001]; 7 int main() 8 { 9 int n,a[100001]; 10 num[0]=1; 11 for(int i=1;i<=100000;i++) 12 num[i]=num[i-1]*2%mod; 13 while(cin>>n) 14 { 15 int m; 16 long long int sum1,sum2; 17 while(n--) 18 { 19 cin>>m; 20 int maxn=-1,minn=100001; 21 sum1=sum2=0; 22 for(int i=1;i<=m;i++) 23 { 24 cin>>a[i]; 25 maxn=max(a[i],maxn); 26 minn=min(a[i],minn); 27 } 28 if(maxn==minn) 29 { 30 sum1=((1+m)*m/2)%mod; 31 sum2=num[m]-1; 32 cout<<sum1<<" "<<sum2<<endl; 33 } 34 else 35 { 36 int t=0,p=0,t1=0,p1=0; 37 for(int i=1;i<=m;i++) 38 { 39 if(a[i]==minn) 40 { 41 t=i; 42 t1++; 43 } 44 if(a[i]==maxn) 45 { 46 p=i; 47 p1++; 48 } 49 sum1=(sum1+min(t,p))%mod; 50 //cout<<sum1<<" "<<min(t,p)<<endl; 51 } 52 sum2=(num[m]-1-num[m-t1]+1-num[m-p1]+1+num[m-t1-p1]-1)%mod; 53 if(sum2<0) 54 sum2+=mod; 55 cout<</*maxn<<" "<<minn<<" "<<p<<" "<<p1<<" "<<*/sum1<<" "<<sum2<<endl; 56 } 57 } 58 } 59 return 0; 60 }
参考博客网址:http://www.cnblogs.com/chenyang920/p/4743955.html
以下是对遍历求和sum1的详细解释:给出3 2 4 1 3 1 2数串,初始化t,p所指位置为0,起始位置为a[1]=3;min(t,p)为最值最小坐标,其实这个就是满足的子串有多少个了;当i遍历到第一个最大值4时,p值为i=3,但t由于未找到最小值依然为0,故min(t,p)依然为0,sum1也还是0,说明目前没有符合的子串,当i变为4,找到最小值1,min(t,p)为3,(意为目前发现3个满足条件的子串:(3-1),(2-1),(4-1)),之后i变为5,由于3不是最值,故t,p,min(t,p)都没变,但此时min(t,p)的意思为找到新的3个满足条件的子串(可以理解为原来找到的子串与不是最值得数合并演变而来的,分别是:(3-3),(2-3),(4-3));到这就基本明白这算式的巧妙之处了;甚是惊讶有木有?所以就能ac了。
以上是关于SPOJ - AMR11H的主要内容,如果未能解决你的问题,请参考以下文章