题目入口
题解令
f
[
i
]
f[i]
f[i]表示到第i个字符的期望长度,
g
[
i
]
g[i]
g[i]表示以第i个字符为结尾的连续o串长度的期望,此时就有三种情况
s
[
i
]
=
=
o
时
,
f
[
i
]
=
f
[
i
−
1
]
+
(
g
[
i
−
1
]
+
1
)
2
−
g
[
i
−
1
]
2
=
f
[
i
−
1
]
+
2
∗
g
[
i
−
1
]
+
1
,
g
[
i
]
=
g
[
i
−
1
]
+
1
s[i] == o 时, f[i] = f[i - 1] + (g[i-1] + 1)^2 -g[i-1]^2 = f[i - 1] + 2 * g[i - 1] + 1,g[i] = g[i -1] + 1
s[i]==o时,f[i]=f[i−1]+(g[i−1]+1)2−g[i−1]2=f[i−1]+2∗g[i−1]+1,g[i]=g[i−1]+1
当
s
[
i
]
=
=
x
时
,
g
[
i
]
=
0
,
f
[
i
]
=
f
[
i
−
1
]
当s[i] == x时,g[i] = 0,f[i] = f[i - 1]
当s[i]==x时,g[i]=0,f[i]=f[i−1]
当
s
[
i
]
=
=
?
时
,
f
[
i
]
=
f
[
i
]
+
(
2
∗
g
[
i
−
1
]
+
1.0
)
∗
p
,
g
[
i
]
=
(
g
[
i
−
1
]
+
1
)
∗
p
(
p
为
?
为
o
的
概
率
,
这
题
是
0.5
)
当s[i] == ?时,f[i] = f[i] + (2 * g[i - 1] + 1.0) * p,g[i]=(g[i - 1] + 1)*p(p为?为o的概率,这题是0.5)
当s[i]==?时,f[i]=f[i]+(2∗g[i−1]+1.0)∗p,g[i]=(g[i−1]+1)∗p(p为?为o的概率,这题是0.5)
#include洛谷P1654 OSU!using namespace std; const int N = 3e5 + 5; double f[N], g[N]; char s[N]; int main() { int n; cin >> n >> s + 1; for(int i = 1; i <= n; i ++ ) { if(s[i] == 'o') { g[i] = g[i - 1] + 1.0; f[i] = f[i - 1] + 2.0 * g[i - 1] + 1.0; } else if(s[i] == 'x') { g[i] = 0; f[i] = f[i - 1]; } else if(s[i] == '?') { g[i] = (g[i - 1] + 1.0) / 2.0; f[i] = f[i - 1] + (2.0 * g[i - 1] + 1.0) / 2.0; } } printf("%.4lf", f[n]); return 0; }
题目入口
题解本题和上题差不多,不同的是本题需要维护长度 l e n len len和 l e n 2 len^2 len2的期望,注意不能只维护 l e n len len的期望,因为 E ( x 2 ) ≠ E ( x ) 2 E(x^2)neq E(x)^2 E(x2)=E(x)2
代码#include2.推公式 P4562 [JXOI2018]游戏using namespace std; const int N = 1e5 + 5; double p; double f[N]; // 到第i个的期望长度 double a[N], b[N]; // len的期望 和 len方的期望 double cal(double x) { return x * x * x; } int main() { cin.tie(0); cout.tie(0); ios::sync_with_stdio(0); int n; cin >> n; double res = 0; double len = 0; double p; for(int i = 1; i <= n; i ++ ) { cin >> p; a[i] = (a[i - 1] + 1) * p; b[i] = (b[i - 1] + (2.0 * a[i - 1] + 1.0)) * p; f[i] = f[i - 1] + ((3.0 * b[i - 1] + 3.0 * a[i - 1] + 1.0)) * p; } printf("%.1lf", f[n]); return 0; }
题目入口
题解我们发现,对于一系列具有倍数关系数字2,4,6,8,检查时间其实是由他们种最小的数所决定的,以样例为例,将2,4分为一类,3分为一类,最后的检查时间是由2和3的位置所决定,所以可以枚举所有可能的时间,排列组合一下即可
代码#includeP3802 小魔女帕琪#define int long long using namespace std; const int mod = 1e9 + 7; const int N = 1e7 + 5; int fac[N], infac[N]; int pre[N]; bool vis[N]; int sz[N]; int qpow(int a, int n, int mod) { int res = 1; while(n) { if(n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; } void init(int n) { //预处理阶乘和逆元 fac[0] = 1; infac[0] = 1; for(int i = 1; i <= n; i ++ ) fac[i] = fac[i - 1] * i % mod; infac[n] = qpow(fac[n], mod - 2, mod); for(int i = n - 1; i >= 1; i -- ) { infac[i] = infac[i + 1] * (i + 1) % mod; } //for(int i = 1; i <= 10; i ++ ) cout << fac[i] << " "; //cout << endl; //for(int j = 1; j <= 10; j ++ ) cout << infac[j] << " "; //cout << endl; } inline int find(int x) { return x == pre[x] ? x : pre[x] = find(pre[x]); } int C(int a, int b) { return fac[a] % mod * infac[a - b] % mod * infac[b] % mod; } signed main() { int l, r; cin >> l >> r; init(r + 1); int n = r - l + 1; int x = 0; // x为最小的数的个数 for(int i = l; i <= r; i ++ ) { if(vis[i]) continue; x ++ ; for(int j = 2; j * i <= r; j ++ ) { if(vis[i * j]) continue; vis[i * j] = true; //cout << i << " " << j << endl; } } //for(int i = l; i <= r; i ++ ) cout << pre[i] << " "; int res = 0; //cout << C(5, 3) << endl; //cout << x << endl; for(int i = x; i <= n; i ++ ) { // 枚举可能的时间 res += x * C(n - x, i - x) % mod * fac[i - 1] % mod * fac[n - i] % mod * i % mod; res %= mod; } // 对于时间是i的情况,说明x个数必须在前i个位置且有一个处于第i个位置,于是固定第i个位置,前面和后面全排列即可 cout << res << endl; return 0; }
题目入口
题解如果我们能知道每七个连续的晶体释放魔法的概率,将所有的可能性加起来便是结果,令 a 1 , a 2 . . . a 7 为 每 种 属 性 的 晶 体 数 量 , a_1,a_2...a_7为每种属性的晶体数量, a1,a2...a7为每种属性的晶体数量,以前七个为例,如果能施放魔法,概率必为 7 ! × C n a 1 × C n − 1 a 2 . . . × C n − 6 a 7 7!times C_n^{a1}times C_{n-1}^{a2}...times C_{n - 6}^{a7} 7!×Cna1×Cn−1a2...×Cn−6a7,7!是因为释放一次魔法时每种属性的晶体位置不确定,接下来我们可以感性的理解一下,对于抽签,在每次不知道前者结果时概率时一样的,本题也可以这么理解,之后每七个能释放魔法的概率均相同,由于长度为7的串一共有 n − 6 n-6 n−6个,最后答案乘上即可
代码#includeusing namespace std; const int N = 10; double f[N], g[N]; int a[N]; double res = 1; int main() { int n = 0; for(int i = 1; i <= 7; i ++ ) { cin >> a[i]; n += a[i]; } int fac7 = 1 * 2 * 3 * 4 * 5 * 6 * 7; bool flag = true; for(int i = 1; i <= 7; i ++ ) { if(n - i + 1 == 0) { flag = false; break; } res *= a[i] * 1.0 / (n - i + 1); } if(!flag) cout << "0.000" << endl; else { res = res * fac7 * (n - 6); printf("%.3lf", res); } return 0; }



