zoukankan      html  css  js  c++  java
  • 【赛后补题】Lucky Probability(CodeForces 110D)

    题意

    给定两个(P,Q)的正整数区间((P,Q)都符合([L,R])这个区间,并且都(le 10^9)),分别从其中随机选出一个数,选出的两个数作为一个新区间的左右端点。要求新区间内的幸运数刚好为(k)个的概率(幸运数指一个数的数位只有4或7)。

    分析

    这题要思考着做。首先能有一个直觉:在(10^9)中间的幸运数肯定不多(2^10左右)。这个可以暴力求出。然后概率如何求?所有的情况一定是((P_r-P_l+1)(Q_r-Q_l+1))这么多,然后符合条件的幸运数区间一共有(l_tot-k+1)个(([Lucky_{i},Lucky_{i+k-1}]))这么多。为了计算所有情况,我们只能遍历所有幸运数区间,看在什么情况下能符合题意(显然不会去遍历(10^9)的P、Q的区间)。对于每个这样的([Lucky_{i},Lucky_{i+k-1}])区间,能够与他们相交的P、Q是存在两种情况的:a)P<Q;b) P>Q。我们分类讨论即可。简单地说,先计算Lucky区间与([P_l,P_r])的交集(相当于在a情况下考虑区间头),然后再计算Lucky区间与([Q_l,Q_r])的交集,将两个结果相乘即是符合第i个幸运区间的可能情况。同样地,还要对反向地(即PQ交换)再计算一遍。注意对(k=1)情况的特判。
    遍历所有的幸运区间后,概率就不难求得了。

    代码(Java)

    /*
     * ACM Code => cf110d.java
     * Written by Sam X
     * Date: 三月, 08, 2019
     * Time: 14:27
     */
    import java.util.*;
    import java.math.*;
    
    public class cf110d
    {
        static ArrayList<Long> vec = new ArrayList<>();
        static void dfs(long x)
        {
            if(x>1e9) return;
            if(x*10+4<1e9)
            {
                vec.add(x*10+4);
                dfs(x*10+4);
            }
            if(x*10+7<1e9)
            {
                vec.add(x*10+7);
                dfs(x*10+7);
            }
        }
        static final long contain(long x1, long y1, long x2, long y2)
        {
            return Math.max(Math.min(y1,y2)-Math.max(x1,x2)+1,0l);
        }
        public static void main(String args[])
        {
            Scanner cin = new Scanner(System.in);
            long pl = cin.nextLong(), 
                 pr = cin.nextLong(), 
                 vl = cin.nextLong(),
                 vr = cin.nextLong(),
                 k = cin.nextLong();
        
            dfs(0);
            vec.add(0l);
            vec.add((long)1e9);
    
            Collections.sort(vec);
            /*
            for(long x: vec)
            {
                System.out.print(x+" ");
            }
            System.out.println();
            */
            long ans=0;
    
            int sz=vec.size()-2;
            for(int i=1; i<=sz-k+1; ++i)
            {
                int j=i+(int)k-1;
                ans+=contain(vec.get(i-1)+1, vec.get(i), pl, pr)*contain(vec.get(j), vec.get(j+1)-1, vl, vr);
                if(vec.get(i)>pr) break;
            }
    
            for(int i=1; i<=sz-k+1; ++i)
            {
                int j=i+(int)k-1;
                ans+=contain(vec.get(i-1)+1, vec.get(i), vl, vr)*contain(vec.get(j), vec.get(j+1)-1, pl, pr);
                if(vec.get(i)>vr) break;
            }
    
            if(k==1)
            {
                for(int i=1; i<=sz; ++i)
                {
                    if(contain(vec.get(i), vec.get(i), pl, pr)!=0 &&
                       contain(vec.get(i), vec.get(i), vl, vr)!=0) ans--;
                }
            }
    
            System.out.printf("%.12f
    ", (double)ans/(vr-vl+1)/(pr-pl+1));
            cin.close();
        }
    }
    
  • 相关阅读:
    html与app交互
    算法:算法的时间与空间复杂度
    php加解密函数集合
    redis主要用法
    【原创】RabbitMQ教程:php实现
    安装RabbitMq
    mysql复制表和字段
    vim文本操作
    JAVA学习(常量)
    JAVA学习(变量)
  • 原文地址:https://www.cnblogs.com/samhx/p/cf110d.html
Copyright © 2011-2022 走看看