PE做题记录
Posted psimonw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PE做题记录相关的知识,希望对你有一定的参考价值。
675
只要猜出\(S(n)\)是个积性函数就好。
正确性显然。
设\((n, m) = 1\)
则
\[
\beginaligned
S(nm)
& = \sum_d | nm 2 ^ \omega (d) \& = \sum_d_1 | n \sum_d_2 | m 2 ^ \omega (d_1 d_2) \& = \sum_d_1 | n \sum_d_2 | m 2 ^ \omega (d_1) + \omega (d_2) \& = \sum_d_1 | n 2 ^ \omega (d_1) \sum_d_2 | m 2 ^ \omega (d_2) \& = S(n) \cdot S(m)
\endaligned
\]
其中,因为\((n, m) = 1\),\((d_1, d_2) = 1\),有\(\omega(d_1) + \omega(d_2) = \omega(d_1 d_2)\)。
现在我们知道\(S\)是积性函数,但不是完全积性,但这足够了。
简单计算可以知道
\[
S(n) =
\begincases
1, & n = 1 \2k + 1, & n = p ^ k, p \in \mathbb P \\endcases
\]
这样,如果\(n = p_1 ^ x_1 p_2 ^ x_2 \ldots p_k ^ x_k\),则
\[
S(n) = \prod_i = 1 ^ k (2x_i + 1)
\]
由于要求
\[
\sum_i = 2 ^ n S(i!)
\]
考虑每次从\(S(i!)\)推向\(S((i+1)!)\),多了一个\(i\),对其中一些素数的个数产生了贡献。
直接把影响到的素因子的个数修改,以及对答案进行修改即可。
注意要线性求逆元。
复杂度\(\mathcal O(n \log \log n)\)。
其中有一些小细节,具体见代码。
#include <bits/stdc++.h>
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair <int, int> pii;
const int N = 1e7 + 5, mod = 1e9 + 87;
int n, las, ans, inv[N << 1], cnt[N]; bool vis[N];
vector <pii> pf[N];
int power (int a, int b)
int ret = 1;
for ( ; b; b >>= 1, a = 1ll * a * a % mod)
if (b & 1)
ret = 1ll * ret * a % mod;
return ret;
int main ()
scanf("%d", &n);
inv[1] = 1;
for (int i = 2; i <= n * 2; ++i)
inv[i] = 1ll * inv[mod % i] * (mod - mod / i) % mod;
for (int i = 2; i <= n; ++i)
if (!vis[i])
pf[i].push_back(mp(i, 1));
for (int j = i + i, k; j <= n; j += i)
vis[j] = 1;
if (j / i % i == 0)
k = pf[j].size();
pf[j].push_back(mp(i, 1 + pf[j / i][k].se));
else
pf[j].push_back(mp(i, 1));
las = 1, ans = 0;
for (int i = 2; i <= n; ++i)
for (auto x : pf[i])
las = 1ll * las * inv[cnt[x.fi] * 2 + 1] % mod;
cnt[x.fi] += x.se;
las = 1ll * las * (cnt[x.fi] * 2 + 1) % mod;
ans = (ans + las) % mod;
printf("%d\n", ans);
return 0;
605
低难度续命题。被续惨了。
设\(p(n, k)\)为\(n\)个人的游戏,第一个人输了round 1
,第\(k\)个人最终赢得游戏的概率,\(q(n, k)\)为\(n\)个人的游戏,第一个人赢了round 1
,第\(k\)个人最终赢得游戏的概率。
则有
\[
p(n, k) = (\frac12) ^ k + 1 - 2 + (\frac12) ^ n - 1 \cdot \frac 12 \cdot p(n, k) \q(n, k) = (\frac12) ^ 2 \cdot \frack - 1 - 2 + 12 ^ k - 1 - 2 + (\frac12) ^ n - 1 \cdot \frac 12 \cdot q(n, k) + (\frac12) ^ n - 1 \cdot n \cdot \frac12 \cdot p(n, k) \ans = \frac12 (p(n, k) + q(n, k))
\]
解得
\[
ans = \frac2 ^ n - k (n + (k - 1)(2 ^ n - 1))(n - 1) ^ 2
\]
但是题目很毒瘤,要求把概率约成最简后输出分子乘分母的乘积。
只是因为这题数据给得好,\(n = 10 ^ 8 + 7, k = 10 ^ 4 + 7\),分子和分母\(\gcd\)刚好为1。
其实也是可以粗略证明的。
设\(g = (numerator, denominator)\),则因为\((2 ^ n - 1, 2 ^ n - k) = 1\),所以\(g = (n + (k - 1)(2 ^ n - 1), (2 ^ n - 1) ^ 2)\)。
我们假设\(g > 1\),那么应当有\((n + (k - 1)(2 ^ n - 1), 2 ^ n - 1) > 1\)。
根据辗转相除,又有\((n, 2 ^ n - 1) > 1\),但是实际上\((n, 2 ^ n - 1) = 1\)(这个等式不成立的概率很小,何况\(n\)还是一个大素数),所以假设不成立。
所以\(g = 1\)。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9;
int n, k, num, den;
int power (int a, int b)
int ret = 1;
for ( ; b; b >>= 1, a = 1ll * a * a % mod)
if (b & 1)
ret = 1ll * ret * a % mod;
return ret;
int main ()
n = 1e8 + 7, k = 1e4 + 7;
num = 1ll * power(2, n - k) * (1ll * (power(2, n) - 1) * (k - 1) % mod + n) % mod;
den = power(power(2, n) - 1, 2);
cout << 1ll * num * den % mod << endl;
return 0;
607
这道题的模型其实就是光的折射,或者说是费马原理。
把它类比为光的折射,根据斯涅尔定理,设入射角为\(\theta_1\),折射角为\(\theta_2\),入射速度为\(v_1\),出射速度为\(v_2\),有
\[
\frac\sin \theta_1v_1 = \frac\sin \theta_2v_2
\]
则可以考虑二分第一个入射角,然后判断平行于沼泽岸的距离是否等于垂直于沼泽岸的距离(\(50 \sqrt 2\))。
#include <bits/stdc++.h>
using namespace std;
const double pi = acos(-1.0), ht = 100.0 / sqrt(2.0), d = 50.0 / sqrt(2.0) - 25.0, rec = pi / 2;
double the[10], l, r, mid, len, t;
int main ()
memset(the, 0, sizeof the);
l = 0, r = rec;
while (r - l >= 1e-12)
mid = (l + r) / 2, len = 0, t = 0;
the[0] = mid, len += d / tan(the[0]), t += d / sin(the[0]) / 10.0;
the[1] = rec - asin(sin(rec - the[0]) / 10 * 9), len += 10.0 / tan(the[1]), t += 10.0 / sin(the[1]) / 9.0;
the[2] = rec - asin(sin(rec - the[1]) / 9 * 8), len += 10.0 / tan(the[2]), t += 10.0 / sin(the[2]) / 8.0;
the[3] = rec - asin(sin(rec - the[2]) / 8 * 7), len += 10.0 / tan(the[3]), t += 10.0 / sin(the[3]) / 7.0;
the[4] = rec - asin(sin(rec - the[3]) / 7 * 6), len += 10.0 / tan(the[4]), t += 10.0 / sin(the[4]) / 6.0;
the[5] = rec - asin(sin(rec - the[4]) / 6 * 5), len += 10.0 / tan(the[5]), t += 10.0 / sin(the[5]) / 5.0;
the[6] = rec - asin(sin(rec - the[5]) / 5 * 10), len += d / tan(the[6]), t += d / sin(the[6]) / 10.0;
if (len > ht)
l = mid;
else
r = mid;
printf("%.10lf\n", t);
return 0;
以上是关于PE做题记录的主要内容,如果未能解决你的问题,请参考以下文章