PE做题记录
675
只要猜出\(S(n)\)是个积性函数就好。
正确性显然。
设\((n, m) = 1\)
则
其中,因为\((n, m) = 1\),\((d_1, d_2) = 1\),有\(\omega(d_1) + \omega(d_2) = \omega(d_1 d_2)\)。
现在我们知道\(S\)是积性函数,但不是完全积性,但这足够了。
简单计算可以知道
这样,如果\(n = p_1 ^ {x_1} p_2 ^ {x_2} \ldots p_k ^ {x_k}\),则
由于要求
考虑每次从\(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\)个人最终赢得游戏的概率。
则有
解得
但是题目很毒瘤,要求把概率约成最简后输出分子乘分母的乘积。
只是因为这题数据给得好,\(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\),有
则可以考虑二分第一个入射角,然后判断平行于沼泽岸的距离是否等于垂直于沼泽岸的距离(\(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;
}
330
奇怪的题。
我只能算出\(a(n)\)的\(OGF\),即\(\mathcal A(x) = \sum_{n = 0} ^ {+\infty} a(n) x ^ n\)。
有
然后用多项式求逆可以求出这个多项式的前若干项。
不过这个模数很特殊,尽管不能做\(NTT\),但是由于\(77777777 = 7 * 11 * 73 * 101 * 137\),我们只要计算出在对几个小模数取模后的答案,用中国剩余定理合并即可。
但是问题是我们要求的是第\({10 ^ 9}\)项。幸运的是,在对这些质数取模的情况下,系数会出现循环节,循环节长度是\(\mathcal O(p ^ 2)\)级别的。
这样我们可以用\(\mathcal O(p ^ 2)\)的复杂度暴力做多项式求逆,然后再计算。
但是题目要求的是令\(a(n) = \frac{A(n) \cdot e + B(n)}{n!}\),这一定得把\(A(n)\)和\(B(n)\)拆开算,也就是要考虑\(a(n)\)的递归式的贡献,会复杂些。
这个坑……只能暂时就这样啦……
浙公网安备 33010602011771号