CodeForces 109B Lucky Probability ——概率

题目描述

洛谷题目

CF题目

思路

先算出在范围内(num[q - 1] < max(qr,vr))所有的只包含4和7的数

但要多算一个

bool able = 1;
inline void dfs(int li)
{
	li为边界
    int i,it = q;
    记录该点的在num的位置
    num[i]表示第i大的只含4,7的数
    for(i = 0;i < 2;i++)
    {
        if(1ll * num[it] * 10 + x[i] > li)
        {
            if(able) num[++q] = 1ll * num[it] * 10 + x[i],able = 0;
            多算的那一个
            return;
        }
        num[++q] = num[it] * 10 + x[i]; 
        dfs(li);
    }
}

然后就分类讨论

#include <cstdio>
#include <string>
#include <iomanip>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long lol;
const int MAXN = 60000;
int x[2] = {4,7},q;
lol ans,num[MAXN];
bool able = 1;
inline void dfs(int li)
{
    int i,it = q;
    for(i = 0;i < 2;i++)
    {
        if(1ll * num[it] * 10 + x[i] > li)
        {
            if(able) num[++q] = 1ll * num[it] * 10 + x[i],able = 0;
            return;
        }
        num[++q] = num[it] * 10 + x[i]; 
        dfs(li);
    }
}
inline void EX(lol &x,lol &y) {lol z = y; y = x;x = z;}
int main()
{
    lol pl,pr,vl,vr;
    int i,j,k;
    cin >> pl >> pr >> vl >> vr >> k;
    if(pl > vl) EX(pl,vl),EX(pr,vr);
    保证一区间的左边界<=右区间的左边界
    dfs(max(pr,vr));
    求<=max(pr,vr)所有的只包含4和7的数和第一个大于max(pr,vr)且只包含4和7的数
    sort(num + 1,num + 1 + q);
    求出来的是乱序 排下序
    for(i = 1;i + k - 1 < q;i++)
    {
    	int j = i + k - 1;
    	题目要求 求恰好包含k个幸运数的概率
    	分成子问题 此时有num[i]~num[j] 共k个幸运数
       	有多少种取法
       	从pl pr中选出x
       	从vl vr中选出y
       	满足num[i-1]<x<=num[i]&&num[j]<=y<num[j+1]  (所以要多算一位)
       	或则num[i-1]<y<=num[i]&&num[j]<=x<num[j+1]
        if(num[i] < min(pl,vl)) continue;
        不可能的情况
        if(num[j] > max(pr,vr)) break;
        此时的num[j]大于了max(pr,vr),num为递增序列,那接下来的若干num[j]也必大于max(pr,vr)
        if(pr < vl)
        { 
        Case1
        当
        pl              pr
        |      x         |
        				    vl     vr
        				 	|   y   |
       pl              pr
        |      x         |
        				    vl     vr
        				 y	|     |这种情况也是有可能的只要num[j+1]>vl&&num[i - 1] < pr
            if(num[i] >= pl&&num[j] <= vr&&num[j + 1] > vl&&num[i - 1] < pr)
                ans += (min(num[i],pr) - max(pl - 1,num[i - 1])) * (min(vr + 1,num[j + 1]) - max(num[j],vl));
              这些min,max都是必要的
            continue;
        }
        if(pr <= vr)
        { 
        |       |
        	|       |
        	但要考虑刚好衔接即vr==pl的情况和两区间重合的情况
        	if(num[i - 1] < pr&&num[j + 1] > vl)
            	ans += (min(num[i],pr) - max(pl - 1,num[i - 1])) * (min(vr + 1,num[j + 1]) - max(num[j],vl));
            if(num[i] >= vl&&num[j] <= pr)
                ans += (num[i] - max(vl - 1,num[i - 1])) * (min(pr + 1,num[j + 1]) - num[j]) - ((k == 1)? 1:0);
        } else {
        这种是算包含的情况
        |          |
        	|   |
            if(num[i] >= vl&&num[j] <= pr&&num[i - 1] < vr)
                ans += (min(num[i],vr) - max(vl - 1,num[i - 1])) * (min(pr + 1,num[j + 1]) - num[j]);
            if(num[j] <= vr&&num[i] >= pl&&num[j + 1] > vl)
                ans += (num[i] - max(pl - 1,num[i - 1])) * (min(vr + 1,num[j + 1]) - max(num[j],vl));
            if(num[i] >= vl&&num[j] <= vr&&k == 1) ans--;
            也要考虑算重的情况
        }
    }
    cout.setf(ios::fixed);
    cout的自动补全0
    cout << fixed << setprecision(12) << ans * 1.0 / (1ll * (pr - pl + 1) * (vr - vl + 1));
    cout的保留位数函数
    return 0;
}
posted @ 2019-08-08 19:16  resftlmuttmotw  阅读(163)  评论(0编辑  收藏  举报