卡片游戏(逆序对)
来源:互联网 发布:单晶和多晶冰糖 知乎 编辑:程序博客网 时间:2024/05/01 19:09
题目描述
小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
提示
【输入输出样例解释1】
【输入输出样例解释1】抽出的卡片
a(保留2位小数)
是否满足l<=a<=r
3
3.00
√
1
1.00
2
2.00
√
4
4.00
3,1
2.00
√
1,2
1.50
2,4
3.00
√
3,1,2
2.00
√
1,2,4
2.33
√
3,1,2,4
2.50
√
【输入输出样例解释2】
由上表得,小W总是可以获得小礼物。因此期望值是1
【数据范围】
对于30%的数据,0<n≤10,000;
对于70%的数据,0<n≤100,000;
对于100%的数据,0<n≤500,000,0<l<r≤100。
由表可得,一共有10种情况,其中有7种情况小W可以获得小礼物。因此小W获得小礼物的期望值是7/10。
solution:首先,容易想到用前缀和s[i]表示,j+1到i的平均数就是(s[i]-s[j])/(i-j) (0<=j<i<=n),由题意得,要求l<=(s[i]-s[j])/(i-j)<=r的次数,要同时满足两个约束,这个不好处理,我们可以先考虑l<=(s[i]-s[j])/(i-j)的次数,再减去(s[i]-s[j])/(i-j)<r的次数,注意,是<r不是<=r+1,这里不一样的,
先来看左边,l<=(s[i]-s[j])/(i-j) <=> l*(i-j)<=s[i]-s[j] <=> s[j]-l*j<=s[i]-l*i 这样子就比较明显了——逆序对,准确地说是顺序对,用归并排序,时间复杂度θ(n lg n)
同理,在做一个s[i]-r*i的顺序对,这个要把等于的去掉。
最好把第一个个数减去第二个个数,就是满足的次数。总次数是n*(n+1)/2,约分一下就解决了。
细节见代码:
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstdlib> #include<cstring> using namespace std; int k1,k2; long long n,ans1,ans2,ans,fm,yf,a[1000000],s[1000000],b[1000000],c[1000000],q[1000000],ll,rr; void ms(int l,int r){ if(l==r) return; int mid=(l+r)>>1; ms(l,mid); ms(mid+1,r); k1=l; k2=mid+1; while(k1<=mid&&k2<=r){ if(b[k1]<=b[k2]){ ans1+=(long long)(r-k2+1); q[k1-l+k2-mid]=b[k1]; k1++; } else{ q[k1-l+k2-mid]=b[k2]; k2++; } } while(k1<=mid){ q[k1-l+k2-mid]=b[k1]; k1++; } while(k2<=r){ q[k1-l+k2-mid]=b[k2]; k2++; } for(int i=l;i<=r;i++) b[i]=q[i-l+1]; } void ms1(int l,int r){ if(l==r) return; int mid=(l+r)>>1; ms1(l,mid); ms1(mid+1,r); k1=l; k2=mid+1; while(k1<=mid&&k2<=r){ if(c[k1]<c[k2]){ ans2+=(long long)(r-k2+1); q[k1-l+k2-mid]=c[k1]; k1++; } else{ q[k1-l+k2-mid]=c[k2]; k2++; } } while(k1<=mid){ q[k1-l+k2-mid]=c[k1]; k1++; } while(k2<=r){ q[k1-l+k2-mid]=c[k2]; k2++; } for(int i=l;i<=r;i++) c[i]=q[i-l+1]; } long long gcd(long long x,long long y){ if(x==0) return y; return gcd(y%x,x); } int main(){ scanf("%d%lld%lld",&n,&ll,&rr); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); s[i]=s[i-1]+a[i]; b[i]=s[i]-ll*i; c[i]=s[i]-rr*i; } ms(0,n); ms1(0,n); ans=ans1-ans2; fm=n*(n+1)/2; yf=gcd(ans,fm); ans/=yf; fm/=yf; if(ans==0) printf("0\n"); else if(ans==fm) printf("1\n"); else printf("%lld/%lld\n",ans,fm); return 0; }
- 卡片游戏(逆序对)
- 卡片游戏(栈)
- 卡片游戏(队列)
- 卡片游戏(1)
- 卡片游戏
- 卡片游戏
- 卡片游戏
- 卡片游戏
- 卡片游戏
- 卡片游戏
- 卡片游戏
- 卡片游戏
- 卡片游戏
- 卡片游戏!!!
- 卡片游戏
- 卡片游戏
- 卡片游戏
- 卡片游戏
- USB host and OTG
- C++语言学习笔记
- 那些程序员之间丧心病狂的鄙视链,你在哪一层?
- (转)周明:未来5-10年,自然语言处理将走向成熟
- Develop Leap Motion in Ubuntu 16.04.02 LTS: SDK install
- 卡片游戏(逆序对)
- 变量的分类——作用域——初始值
- javaScript系列之网页与用户交互(五)
- SDUT-2557 分段函数
- js获取当前页面的URL
- 交换两个变量的值,不使用第三个变量的方法及实现
- 文章标题
- Android开发如何写出优雅的代码
- Spring JPA 使用@CreatedDate、@CreatedBy、@LastModifiedDate、@LastModifiedBy 自动生成时间和修改者