萌萌哒身高差(找规律)

链接: https://www.nowcoder.com/acm/contest/117/C
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
Special Judge, 64bit IO Format: %lld

题目描述

“清明时节雨纷纷,路上行人欲断魂。”

然而wfy同学的心情是愉快的,因为BNU ACM队出去春游啦!并且,嗯。。。

以下是wfy同学的日记:

昨天,何老师告诉我们:明天我们去春游,大家准备好喝的和吃的哦!
大家听了都兴奋起来,有的欢呼,有的鼓掌,开心得不得了。第二天,我们早早地来到学校,迫不及待地上了车,来到了公园。一进门,啊,太美了!公园中有那么多树,有高有矮,有粗有瘦,密密的,在春风吹拂下轻轻摇摆着,像是欢迎我们的到来。公园中有那么多的鲜花,有红有黄,有紫有白,散发着淡淡的清香,闻得我们都醉了。公园的边角上有一条清澈的小河,河水缓缓地流淌着,可以看到水里的鱼儿在快活地游来游去,多自在啊!水草碧绿碧绿的,多新鲜啊!小河的旁边是一片小树林,远远望去一片鲜绿。我们在里面吃东西、做游戏、捉迷藏,玩得疯极了。树林的后面是连绵起伏的小山坡,蜿蜿的真像一条游动的蛇。当然,我觉得公园的天空也很美。它万里无云,一碧如洗,很清澈。小鸟在展翅飞翔,它们形态各异,一会儿上升,一会儿下滑,一会儿吃虫,一会儿在小树林里休息,非常悠闲。快乐时光总是那么短暂,很快,天色就昏暗了。我们依依不舍地上了车,回到了学校,我真希望明年的春天还能再来看看这美丽的公园。
回到学校后,何老师说:请大家排成一排,我们来拍照片啦!
何老师特别喜欢萌的东西,比如**,比如****,等等。
何老师认为,同学们站成一排时,相邻两个同学身高相差越多,这两个同学站在一起越萌。
那么所有相邻两个同学的身高差加起来越大,拍出来的照片就越萌,也就是这张照片的萌力指数。
何老师希望拍出来的照片的萌力指数尽可能大。
然而何老师并不是数学老师,而是语文老师。何老师觉得很GG。
何老师只想知道,如果让同学们随便站成一排(站成所有排列的可能性都相等),萌力指数的数学期望是多少。
聪明的我一下子就算出了答案,然后何老师就奖励了我一个很萌的礼物。
今天真的好开心。

BNU ACM队共有n名同学,身高分别是,聪明的你能计算出何老师想要的数学期望吗?

输入描述:

第一个是一个正整数T(T ≤ 20),表示测试数据的组数,
每组测试数据只有一行,包含一个整数n(2 ≤ n ≤ 100)。

输出描述:

 
  

对于每组测试数据,输出一行,包含一个实数,表示萌力指数的数学期望值,要求相对误差不超过,也就是说,令输出结果为a,标准答案为b,若满足,则输出结果会被认为是正确答案。

输入

2
2
3

输出

1.000000000000
2.666666666667

说明

对于第二组样例,所有可能的排列是[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1],所以答案是

本题思路:打表找规律

规律是:从2~100,小数点之前有规律为,如果能被3整除,num[n]=num[n-1]+2*(i/3-1)+1+M(M=0.666666666667);否则num[n]=num[n-1]+2*(i/3)+1;其中num[1]=0.0;

打表代码:(由于时间复杂度太高,只能算前13个数)

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        double n;
        cin>>n;
        int x=(int)n;
        double a[x];
        double j=1;
        for(int i=0;i<n;i++){
            a[i]=j;j++;
        }
        double sum=0;
        double temp=0;
        double cnt=0;
        do
        {
            cnt++;///printf("cnt=%lf\n",cnt);
            temp=0;
            for(int i=1;i<x;i++)
                temp+=abs(a[i]-a[i-1]);
            ///printf("temp=%lf\n",temp);
            sum+=temp;
        }while(next_permutation(a,a+x));
        printf("%.12lf\n",sum/cnt);
    }
    return 0;
}

第一次提交的代码由于忽略了输入的数据有重复的,一旦输入的数据中有重复的值,就会因为代码中的if出现原理上的偏差。错误的代码是:

#include<cstdio>
#include<iostream>
using namespace std;
double M=0.666666666667;
int main()
{
    double num[105];
    num[1]=0.0;
    for(int i=2;i<=101;i++)
    {
        if(i%3!=0)
            num[i]=num[i-1]+2*(i/3)+1;
        else
            num[i]=num[i-1]+2*((i-1)/3)+1;
    }
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        if(n%3==0)
            num[n]+=M;
        printf("%.12lf\n",num[n]);
    }
    return 0;
}

AC代码是:

#include<cstdio>
#include<iostream>
using namespace std;
double M=0.666666666667;
int main()
{
    double num[105];
    num[1]=0.0;
    for(int i=2;i<=101;i++)
    {
        if(i%3!=0)
            num[i]=(int)num[i-1]+2*(i/3)+1;
        else
            num[i]=num[i-1]+2*((i-1)/3)+1+M;
    }
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        printf("%.12lf\n",num[n]);
    }
    return 0;
}

另一种思路解这道题:因为是全排列,也就是n个人,他要与剩余的n-1个人求身高差之和ant。(第一个代码中)因为全排列求同学i和同学j差值的和sum会有重复,去掉重复后悔发现sum/cnt(n的全排列的个数)正好等于ant/n,于是有:

#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#define maxn 105
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        double ant=0,temp=0;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
        {
            if(i!=j){
                temp=abs(i-j);
                ant+=temp;
            }
            ///cout<<"**"<<temp<<endl;
        }
        printf("%.12f\n",ant/(1.0*n));
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/a17865569022/article/details/80139060
今日推荐