【问题描述】
有N个数,随机选择一段区间,如果这段区间的所有数的平均值在[l,r]中则
你比较厉害。求你比较厉害的概率。
【输入格式】
第一行有三个数N,l,r,含义如上描述。
接下来一行有N个数代表每一个数的值。
【输出格式】
输出一行一个分数a/b 代表答案,其中a,b互质。如果答案为整数则直接输出该整数即可。
【样例输入 1】
4 2 3
3 1 2 4
【样例输出 1】
7/10
【样例输入 2】
4 1 4
3 1 2 4
【样例输出 2】
1
【样例解释】
塔外面有棵树。
【数据规模与约定】
30%的数据,1<=N<=104 。
60%的数据,1 ≤N≤ 10 5 。
对于100%的数据,1 ≤ N≤ 5× 10 5 ,0 < L ≤ R ≤ 100。
______________________________________________________________________
很神奇的数学题,难在推公式,并把公式和信息学的东西联系起来。这是信息题吗?算是数学信息题吧!!!
推理过程:
1、求区间平均值在【l,r】间的概率
2、求平均值在[l,r]间的个数,在除以n(n+1)就可以了
3、[l,r]间的个数=小于等于r的个数-小于l的个数
4、小于l可以表示为(a[i]+a[i+1]+a[i+2]+……+a[i+k-1])/k<l
继续推出(a[i]+a[i+1]+a[i+2]+……+a[i+k-1])<l*k
再推出(a[i]+a[i+1]+a[i+2]+……+a[i+k-1])-l*k<0
再再推出(a[i]-l+a[i+1]-l+a[i+2]-l+……+a[i+k-1]-l)<0
让数组b[i]=a[i]-l;
公式变为b[i]+b[i+1]+b[i+2]+……+b[i+k-1]<0
用前缀和维护可得:s[i+k-1]-s[i-1]<0;
这是什么?逆序对!!!逆序对的个数就是小于l的个数
同理求出小于等于r的个数。差,OK!
神啊!再让我做一遍,我还是做不出来!!!
______________________________________________________________________
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 6 using namespace std; 7 long long n,l,r,ans1,ans2; 8 long long a[500010],b[500010],c[500010],d[500010]; 9 void readlong(long long &x) 10 { 11 char c=getchar(); 12 int fh=1; 13 for(;c>‘9‘||c<‘0‘;c=getchar())if(c==‘-‘)fh*=-1; 14 x=0; 15 for(;c<=‘9‘&&c>=‘0‘;c=getchar())x=x*10+c-‘0‘; 16 x=x*fh; 17 } 18 19 void nxd1(long long l,long long r) 20 { 21 if(l==r)return; 22 long long mid=(l+r)/2; 23 nxd1(l,mid);nxd1(mid+1,r); 24 long long z=l,y=mid+1,x=l; 25 while(z<=mid&&y<=r) 26 { 27 if(b[z]>b[y]) 28 { 29 ans1+=mid-z+1; 30 d[x++]=b[y];y++; 31 } 32 else 33 { 34 d[x++]=b[z];z++; 35 } 36 } 37 while(z<=mid) 38 { 39 d[x++]=b[z];z++; 40 } 41 while(y<=r) 42 { 43 d[x++]=b[y];y++; 44 } 45 memcpy(b+l,d+l,(r-l+1)*8); 46 } 47 void nxd2(long long l,long long r) 48 { 49 if(l==r)return; 50 long long mid=(l+r)/2; 51 nxd2(l,mid);nxd2(mid+1,r); 52 long long z=l,y=mid+1,x=l; 53 while(z<=mid&&y<=r) 54 { 55 if(c[z]>=c[y]) 56 { 57 ans2+=mid-z+1; 58 d[x++]=c[y];y++; 59 } 60 else 61 { 62 d[x++]=c[z];z++; 63 } 64 } 65 while(z<=mid) 66 { 67 d[x++]=c[z];z++; 68 } 69 while(y<=r) 70 { 71 d[x++]=c[y];y++; 72 } 73 memcpy(c+l,d+l,(r-l+1)*8); 74 } 75 int main() 76 { 77 freopen("jian.in","r",stdin); 78 freopen("jian.out","w",stdout); 79 readlong(n);readlong(l);readlong(r); 80 for(long long i=1;i<=n;i++) 81 { 82 readlong(a[i]); 83 b[i]=b[i-1]+a[i]-l; 84 c[i]=c[i-1]+a[i]-r; 85 } 86 ans1=0;nxd1(0,n); 87 ans2=0;nxd2(0,n); 88 ans2-=ans1; 89 ans1=n*(n+1)/2; 90 if(ans2==0) 91 { 92 cout<<"0"<<endl;return 0; 93 } 94 if(ans2==ans1) 95 { 96 cout<<"1"<<endl;return 0; 97 } 98 long long g=__gcd(ans1,ans2); 99 cout<<ans2/g<<"/"<<ans1/g<<endl; 100 fclose(stdin); 101 fclose(stdout); 102 return 0; 103 }