问题 E: 卡片游戏
时间限制: 1 Sec 内存限制: 128 MB提交: 42 解决: 18
[提交][状态][讨论版]
题目描述
小D举办了元旦联欢活动,其中有一个卡片游戏。
游戏的规则是这样的:有n张卡片,每张卡片上正面写着一个小于等于100的正整数ai,反面都是一样的花色。这n张卡片正面朝下叠成一堆,玩这个游戏的人从中可以抽出连续的k(1≤k≤n)张卡片。如果对于这k张卡片上的数字的平均值a,满足l<=a<=r,那他就可以获得小礼物一件。
小W来玩这个游戏了,她事先通过某些途径知道了这n张卡片上写的数字,现在她想知道她获得小礼物的期望值。
小W对小数很头疼,所以请你用分数的形式告诉她答案。
输入
输入文件名为game.in
输入第1行,三个整数n,l,r。
第2行,包含n个整数ai。
输出
输出文件名为game.out
输出仅1行,表示小W获得小礼物的期望值。输出格式为“P/Q”(P和Q互质)。如果期望值是0或1就不用输出分数了
样例输入
game.in
4 2 3
3 1 2 4
game.out
7/10
样例输出
【输入输出样例2】
game.in
4 1 4
3 1 2 4
game.out
1
这道题很考验数学功力,首先很容易想到判断条件的变形就是令sum[i]表示前i个数的前缀和
所以题目给出的条件等价于l<=( (sum[j]-sum[i-1])/(j-(i-1)) )<=r
我们令中间那个东西为x,所以原题的方案数就是x>=l的方案数减去x>r的方案数
所以(sum[j]-sum[i-1])/(j-(i-1))>=l <==> sum[j]-sum[i-1]>=j*l-(i-1)*l
所以(i-1)*l-sum[i-1]>=l*j-sum[j] 令a[i]=(i-1)*l-sum[i],求一下逆序对就行了(这里是<=不是经典的逆序对)
然后就再令b[i]=(i-1)*r-sum[i],求一下经典逆序对,答案相减就行啦
#include<iostream> #include<cstdio> #include<algorithm> #define N 500005 using namespace std; #define ll long long ll a[N],b[N],n,L,R,tot,c[N]; void Merge_sort(ll l,ll r) { if(l==r) { return; } ll mid=(l+r)>>1; Merge_sort(l,mid); Merge_sort(mid+1,r); ll i=l,j=mid+1,k=l; while(i<=mid&&j<=r) { if(a[i]<a[j]) { b[k++]=a[i++]; }else { b[k++]=a[j++]; tot+=mid-i+1; } } while(i<=mid) { b[k++]=a[i++]; } while(j<=r) { b[k++]=a[j++]; } for(ll i=l;i<=r;i++) a[i]=b[i]; } void Merge_sort_(ll l,ll r) { if(l==r) { return; } ll mid=(l+r)>>1; Merge_sort_(l,mid); Merge_sort_(mid+1,r); ll i=l,j=mid+1,k=l; while(i<=mid&&j<=r) { if(c[i]<=c[j]) { b[k++]=c[i++]; }else { b[k++]=c[j++]; tot+=mid-i+1; } } while(i<=mid) { b[k++]=c[i++]; } while(j<=r) { b[k++]=c[j++]; } for(ll i=l;i<=r;i++) c[i]=b[i]; } ll C(ll x) { return (ll)(x*(x+1)/2); } ll gcd(ll a,ll b) { if(b==0) return a; return gcd(b,a%b); } void print(ll a,ll b) { if(a==0) { cout<<0<<endl; return; } if(a==b) { cout<<1<<endl; return; } ll c=gcd(a,b); cout<<a/c<<'/'<<b/c<<endl; } int main() { ios::sync_with_stdio(false); cin>>n>>L>>R; a[0]=c[0]=0; ll sum=0; for(ll i=1;i<=n;i++) { ll t; cin>>t; sum+=t; a[i]=L*i-sum; c[i]=R*i-sum; } Merge_sort(0,n); ll ans=tot; tot=0; Merge_sort_(0,n); ans-=tot; print(ans,C(n)); }