Codeforces 54C First Digit Law 数位dp+概率dp

题目链接:点击打开链接

题意:

给定n个区间

下面n个区间

从每个区间中任选一个数。则一共选出了n个数

给出K(<=100)

问选出的n个数中 最高位是1的个数 占n个数的百分之K以上的概率是多少。

先求出对于第i个区间 ,选出的数最高位是1的概率P[i]

dp[i][j] 表示前i个数选了j个最高位是1的概率.


//////////////////////////////////////
//**********************************//
//* ======= lalalalalala ========= *//
//* ------------------------------ *//
//**********************************//
//////////////////////////////////////
									///
#include        <map>              ///
#include       <set>             ///
#include      <list>           ///
#include     <cmath>          ///
#include      <queue>          ///
#include       <deque>           ///
#include        <vector>           ///
#include        <string>           ///
#include       <cstdio>          ///
#include      <cstdlib>        ///
#include       <cstdarg>       ///
#include        <string.h>       ///
#include         <iostream>        ///
#include         <algorithm>        ///
//////////////////////////////////////
typedef long long ll;
template <class T>
inline bool rd(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
template <class T>
inline void pt(T x) {
	if (x <0) {
		putchar('-');
		x = -x;
	}
	if (x>9) pt(x / 10);
	putchar(x % 10 + '0');
}
using namespace std;
ll solve(ll x){
	ll ans = 0, len = 0, high = 0, tmp = x, ten = 1;
	while (tmp){
		len++; 
		high = tmp % 10;
		tmp /= 10;
	}
	for (int i = 1; i < len; i++, ten *= 10)
		ans += ten;
	if (high > 1)return ans + ten;
	else if (high == 1)return ans + x - ten + 1;
	return ans;
}
const int N = 1005;
int n;
double p[N], K;
double dp[N][N]; //dp[i][j]表示前i个选了j个1的概率
int main(){
	while (cin >> n){
		for (int i = 1; i <= n; i++){
			ll l, r; rd(l); rd(r);
			p[i] = (double)(solve(r) - solve(l-1)) / (r - l + 1);
		}
		rd(K);
		memset(dp, 0, sizeof dp);
		dp[0][0] = 1;
		for (int i = 0; i < n; i++){
			for (int j = 0; j <= i; j++)
			{
				dp[i + 1][j] += dp[i][j] * (1 - p[i + 1]);
				dp[i + 1][j + 1] += dp[i][j] * p[i + 1];
			}
		}

		double ans = 0;
		for (int i = 0; i <= n; i++)
		if (double(i) >= K*n/100.0)
			ans += dp[n][i];
		printf("%.10f\n", ans);
	}
	return 0;
}


你可能感兴趣的:(Codeforces 54C First Digit Law 数位dp+概率dp)