问题描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿。终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 输入格式 输入文件第一行包含两个正整数N和M。N为袜子的数量,M为小Z所提的询问的数量。 输出格式 输出文件包含M行,对于每个询问在一行中输出分数A/B表示从该询问的区间[L,R]中随机抽出两只袜子颜色相同的概率。若该概率为0则输出0/1,否则输出的A/B必须为最简分数。(详见样例) |
样例输入 6 4 |
样例输出 2/5 |
样例说明 询问1:共C(5,2)=10种可能,其中抽出两个2有1种可能,抽出两个3有3种可能,概率为(1+3)/10=4/10=2/5。 数据规模和约定 30%的数据中 N,M ≤ 5000; |
思路如下:
计算分子:利用 set 的不可重复性和 multiset 的可重复性,以及set 中 count()方法,便于统计,以求得分子。
计算分母:利用组合数原理。
另外约分需要注意。(构造 辗转相除法 函数)
#include<iostream>
#include<bits/stdc++.h>
#include<set>
using namespace std;
int gcd(int m, int n) {
return n ? gcd(n, m % n) : m;
} //辗转相除法 求得最大公约数,以化简最简分数
int main()
{
multiset<int> s; //存入可重复的数据
set<int> s1; //存入不可重复的数据
int n,m;
cin>>n>>m;
int a[n+10];
for(int i=1;i<=n;i++){
cin>>a[i];
}
while(m>=1) // 输入有序对
{
int x,y;
cin>>x>>y; //区间输入
for(int j=x;j<=y;j++){
s.insert(a[j]); //存入所有数据
s1.insert(a[j]); //存入不重复的数据
}
set<int>::iterator it;
int e=1,b[n+10];
int sum=0;
for(it=s1.begin();it!=s1.end();it++)
{
int q=s.count(*it); //统计一个数字的重复次数
if(q>1){
sum+=((q-1)*q)/2; //计算分子
}
}
if(sum==0) cout<<"0/1"<<endl;
else {
int z=(((y-x)*(y-x+1))/2); //计算分母
cout<< sum/(gcd(sum,z))<<"/"<<z/(gcd(sum,z))<<endl; //计算结果
}
s.clear();
s1.clear(); //清除set 数据 为了下次使用
m--;
}
return 0;
}