题目描述
思路
先算出在范围内(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;
}