标签:cout make c++ 答案 size bit round print lin
只要猜出\(S(n)\)是个积性函数就好。
正确性显然。
设\((n, m) = 1\)
则
\[
\begin{aligned}
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)
\end{aligned}
\]
其中,因为\((n, m) = 1\),\((d_1, d_2) = 1\),有\(\omega(d_1) + \omega(d_2) = \omega(d_1 d_2)\)。
现在我们知道\(S\)是积性函数,但不是完全积性,但这足够了。
简单计算可以知道
\[
S(n) =
\begin{cases}
1, & n = 1 \2k + 1, & n = p ^ k, p \in \mathbb {P} \\end{cases}
\]
这样,如果\(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;
}
低难度续命题。被续惨了。
设\(p(n, k)\)为\(n\)个人的游戏,第一个人输了round 1
,第\(k\)个人最终赢得游戏的概率,\(q(n, k)\)为\(n\)个人的游戏,第一个人赢了round 1
,第\(k\)个人最终赢得游戏的概率。
则有
\[
p(n, k) = (\frac{1}{2}) ^ {k + 1 - 2} + (\frac{1}{2}) ^ {n - 1} \cdot \frac {1}{2} \cdot p(n, k) \q(n, k) = (\frac{1}{2}) ^ 2 \cdot \frac{k - 1 - 2 + 1}{2 ^ {k - 1 - 2}} + (\frac{1}{2}) ^ {n - 1} \cdot \frac {1}{2} \cdot q(n, k) + (\frac{1}{2}) ^ {n - 1} \cdot n \cdot \frac{1}{2} \cdot p(n, k) \ans = \frac{1}{2} (p(n, k) + q(n, k))
\]
解得
\[
ans = \frac{2 ^ {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;
}
这道题的模型其实就是光的折射,或者说是费马原理。
把它类比为光的折射,根据斯涅尔定理,设入射角为\(\theta_1\),折射角为\(\theta_2\),入射速度为\(v_1\),出射速度为\(v_2\),有
\[
\frac{\sin \theta_1}{v_1} = \frac{\sin \theta_2}{v_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;
}
标签:cout make c++ 答案 size bit round print lin
原文地址:https://www.cnblogs.com/psimonw/p/11626387.html