牛客练习赛38 出题人的RP值,出题人的女装,出题人的手环 解题报告

版权声明:抱最大的希望,为最大的努力,做最坏的打算。 https://blog.csdn.net/qq_37748451/article/details/86548581
链接:https://ac.nowcoder.com/acm/contest/358/A
来源:牛客网

众所周知,每个人都有自己的rp值(是个非负实数),膜别人可以从别人身上吸取rp值。
然而当你膜别人时,别人也会来膜你,互膜一段时间后,你们就平分了两人原有的rp值,当你膜过一个人之后,你就不能再膜那个人了
出题人发现自己的rp值为x,出题人周围有n个人,第i个人的rp值为a[i]
你要选择膜哪些人和膜人的顺序,使出题人的最终rp值最大

输入描述:
第一行两个数n,x,人数和出题人的初始rp值
第二行n个数,第i个数a[i]表示第i个人的rp值
输出描述:
一行一个数表示出题人的最终rp值(保留三位小数)
示例1
输入
复制
1 0
1
输出
复制
0.500
备注:
数据范围:
n<=100000,a[i]<=100000,x<=100000,(a[i],x都是整数)

 思路:排个序然后从小到大地和自己大的数取平均数

#include<bits/stdc++.h>
#define MOD 1000000007
#define INF 0x3f3f3f3f
using namespace std;
#define ll long long int
const ll MAXN=1e5+5;
int n;
double x;
double a[MAXN];
int main()
{
    scanf("%d%lf",&n,&x);
    for(int i=1;i<=n;i++)
        scanf("%lf",&a[i]);
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++)
    {
        double t=(x+a[i])/2.0;
        if(t>x)
        {
            x=t;
        }
    }
    cout<<fixed<<setprecision(3)<<x<<endl;
    return 0;
}
链接:https://ac.nowcoder.com/acm/contest/358/B
来源:牛客网

题目描述 
出题人早上起床就打算穿衣服,他有两箱衣服,因为懒,他在这两天只打算打开一个箱子.
两个箱子中一个有n件衣服,其中有x件女装,另一个有m件衣服,其中有y件女装.
出题人在第一天随机挑一个箱子后,接下来的两天就会从此箱子中随机找一件衣服穿.
又因为出题人懒而且很有钱,所以他穿完衣服后不会去洗,而是直接扔进垃圾桶,也不会放回原来的箱子.

已知出题人第1天穿了女装,求他第二天依然穿女装的概率

输入描述:
第一行包含5个整数n,m,x,y,t
输出描述:
若t=0,则在第一行输出概率(四舍五入保留小数点后3位,概率为0输出0.000,概率为100%输出1.000)
若t=1,则在第一行输出概率(最简分数形式,概率为0输出0/1,概率为100%输出1/1)
示例1
输入
复制
10 10 8 8 1
输出
复制
7/9
备注:
2<=n,m<=10000
2<=x<=n且2<=y<=m

思路:贝叶斯定理

           已经知道第一天穿女装了,那么选取两个箱子的概率就不是1:1

           ans=p(两次都取到女装)/p(第一次取到女装)

           p(两次都取到女装)=(1/2)*[(x*(x-1))/(n*(n-1))   + (y*(y-1))/(m*(m-1)) ]

           p(第一次取到女装)=(1/2)*[x/n + y/m]

           long long 暴力求分子和分母化简就好

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN=1e5+5;
ll t,n,m,x,y;
ll gcd(ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}
 
int main()
{
    scanf("%lld%lld%lld%lld%lld",&n,&m,&x,&y,&t);
    ll xx=x*(x-1)*m*(m-1)+y*(y-1)*n*(n-1);
    ll yy=(n-1)*(m-1)*(x*m+n*y);
    ll gc=gcd(xx,yy);
    xx=xx/gc;
    yy=yy/gc;
 
    if(t==1)
        cout<<xx<<"/"<<yy<<endl;
    else{
        double ans=1.0*xx/yy+0.0005;
        cout<<fixed<<setprecision(3)<<ans<<endl;
    }
    return 0;
}
链接:https://ac.nowcoder.com/acm/contest/358/D
来源:牛客网

题目描述 
出题人的妹子送了出题人一个手环,这个手环上有 n 个珠子,每个珠子上有一个数。
有一天,出题人和妹子分手了,想把这个手环从两个珠子间切开,并按顺时针顺序展开成一条链。
可以发现,这条链一共有 n 种可能性。求这 n 种可能性的逆序对数之积模 1000000007。
输入描述:
第一行一个数 n,表示珠子个数。
接下来一行 n 个数,以顺时针顺序给出每个珠子上的整数
输出描述:
一个数,表示答案。
示例1
输入
复制
4
1 3 2 3
输出
复制
24
说明
一共有 4 种方式:
1 3 2 3;3 1 3 2;2 3 1 3;3 2 3 1;
逆序对数分别为 1,3,2,4,积为 24。
备注:
n<=200000,-10^9<=珠子上的整数<=10^9。

树状数组离散化再去求逆序对数 

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAXN 200005
#define mod 1000000007
struct AA
{
    int rt,x,t;
    bool operator<(const AA&aa)const
    {
        if(x==aa.x) return rt<aa.rt;
        return x<aa.x;
    }
}ppos[200005];
bool cmp(AA aa,AA bb)
{
    return aa.rt<bb.rt;
}
ll a[500005],summ[500005];
ll ans,answ;
int lowbit(int i)
{
    return i&(-i);
}
void add(int i)
{
    while(i<=MAXN)
    {
        a[i]++;
        i+=lowbit(i);
    }
    return;
}
ll sum(int i)
{
    ll s=0;
    while(i>0)
    {
        s+=a[i];
        i-=lowbit(i);
    }
    return s;
}
int n;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&ppos[i].x);
        ppos[i].rt=i;
    }
    sort(ppos+1,ppos+1+n);
    ppos[1].t=1;
    summ[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(ppos[i].x==ppos[i-1].x)
           ppos[i].t=ppos[i-1].t;
        else
           ppos[i].t=ppos[i-1].t+1;
        summ[ppos[i].t]=i;
    }
    sort(ppos+1,ppos+1+n,cmp);
 
    for(int i=1;i<=n;i++)
    {
        add(ppos[i].t);
        ans+=i-sum(ppos[i].t);
        ans%=mod;
    }
    answ=ans%mod;
 
    for(int i=1;i<n;i++)
    {
        ans+=(n-summ[ppos[i].t])-summ[ppos[i].t-1];
        ans=(ans+mod)%mod;
        answ*=ans;
        answ%=mod;
    }
    printf("%lld\n",answ);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37748451/article/details/86548581