• 🔺 Garbage Remembering Exam UVA


    题目大意:给你N个单词,有两种方法随机排列,一种随机排成一行,另一种随机排成一圈,当两个单词之间的距离在两种排列中都严格小于K时,则这两个单词构成无效单词,问无效单词的期望。
    解题思路:首先对于一排单词的每个单词,取出距离它为K的单词,然后把取出的单词放到环形序列的这个单词的两边
    如果我们能分别算出1-n的有效概率,那么就等于算出了无效概率

    其中 x为当前单词的左右距离为k的单词的个数, 分子是把一排单词中一个单词的有效距离的单词取出来全排列到环形的无效距离内,然后剩余的单词全排列;

    考虑到排列与组合数据过大,用  exp()函数,其中log(N!)=log(N)+log(N-1)+...+log(1);

    需要注意  用long double能过。。。

    代码如下:

    没大弄明白为什么n-1-x < 2*k 的时候不考虑

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define N 100005
    long double temp[N];
    int n,k;
    double solve()
    {
        if(n==1) return 0;//只有一个单词,无效为0
        else if(2*k+1>=n) return n;//如果圈中的一个单词从左边或右边距离都小于K,则该单词无效,所有单词等效
        double ret=0;
        for(int i=1;i<=n;i++)
        {
            int x=min(k,i-1)+min(k,n-i);//一个单词左右k范围内的单词个数
            if(n-1-x-2*k>=0)
            {
                ret+=exp(temp[n-1-x]+temp[n-1-2*k]-temp[n-1]-temp[n-1-x-2*k]);
            }
    //        else
    //            ret += exp(temp[2*k] - temp[2*k-n+1+x] + temp[x] - temp[n-1]);
        }
        return n-ret;
    }
    int main()
    {
        temp[0]=0;
        for(int i=1;i<N;i++)
            temp[i]=temp[i-1]+log((long double)i);
        int cas=1;
        while(scanf("%d%d",&n,&k))
        {
            if(n==0&&k==0) break;
            printf("Case %d: %.4lf
    ",cas++,solve());
        }
        return 0;
    }
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    SASS常用方法
    Vue 全局过滤和局部过滤
    Java进阶知识点8:高可扩展架构的利器
    InnoDB MVCC RR隔离级别下的数据可见性总结
    记一次诡异的网络故障排除
    数据库的读锁和写锁在业务上的应用场景总结
    Gradle配置IDEA正常识别JPA Metamodel Generator动态生成的代码
    程序员容易读错的单词
    Java进阶知识点7:不要只会写synchronized
    Java进阶知识点6:并发容器背后的设计理念
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/9354057.html
Copyright © 2020-2023  润新知