照亮数学的七道光芒 T1-4
照亮数学的七道光芒
勇气
对于第 次攻击,其攻击力为:
对于这个题,显然就是找最小的 使满足这个式子
以 为底取对数,有
如果 答案直接就是零,如果 而 则无解。
signed main()
{
cin >> x >> n;
if (x == 2 && n > 2)
{
cout << "inf";
return 0;
}
else if (x == 2 && n == 2)
{
cout << 1;
return 0;
}
else if (n == 1)
{
cout << 0;
return 0;
}
int times = (ceil)(n - 2) / (log2(x) - 1);
int check = 1;
if (check >= times)
{
cout << 0;
return 0;
}
for (rint i = 1; ; i++)
{
check *= 2;
if (check >= times)
{
cout << i;
return 0;
}
}
}
奉献
仔细读题寻找性质,当且仅当 时,它没有在之前被填写过
将朴素式子列出来:
其中 为 bool
型,当且仅当 时为 ,否则为 。
将式子进行转化:
即为:
这些东西我们都是会求的,这个题最后一个地方,在于 不能直接求,差分一下。
void init()
{
v[1] = phi[1] = 1;
for (rint i = 2; i <= n; i++)
{
if (!v[i])
{
prime[++cnt] = i;
phi[i] = i - 1;
}
for (rint j = 1; prime[j] * i <= n && j <= cnt; j++)
{
v[i * prime[j]] = 1;
if (!(i % prime[j]))
{
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
}
signed main()
{
cin >> n;
init();
for (rint i = 1; i <= n; i++)
{
d[i] = 1 + d[i / 10];
s[i] = s[i - 1] + d[i];
}
for (rint i = 1; i <= n; i++)
{
double sum = ((double)log2(d[i]) * d[i] + s[n / i]) * phi[i];
ans += sum;
}
cout << fixed << setprecision(10) << ans << endl;
return 0;
}
高洁
前置知识 The Sum of the k-th Powers
求
答案是一个 次多项式,考虑找 个值带进去拉格朗日插值
组点值,有 次多项式 的拉格朗日插值:
复杂度为 .
在此题中把 到 带入,有对于每个 ,分母是 乘到 再乘上 乘到 ,这可以预处理阶乘 处理。分子可以预处理前后缀积来 得到
复杂度为
signed main()
{
cin >> n >> k;
pl[0] = pr[k + 3] = fac[0] = 1;
for (rint i = 1; i <= k + 2; i++) pl[i] = pl[i - 1] * (n - i) % mod;
for (rint i = k + 2; i >= 1; i--) pr[i] = pr[i + 1] * (n - i) % mod;
for (rint i = 1; i <= k + 2; i++) fac[i] = fac[i - 1] * i % mod;
for (rint i = 1; i <= k + 2; i++)
{
y = (y + qpow(i, k)) % mod;
int a = pl[i - 1] * pr[i + 1] % mod;
int b = fac[i - 1] * ((k - i) & 1 ? -1 : 1) * fac[k + 2 - i] % mod;
ans = (ans + y * a % mod * qpow(b, mod - 2) % mod) % mod;
}
cout << (ans + mod) % mod << endl;
return 0;
}
在看我们的原题
只和 有关。枚举 的因数,考虑它的倍数对答案的贡献。
结果为 。
整理得:
为 的所有质因子在 中出现次数与在 中出现次数的商的最大值,可以在枚举 时计算。 前置只是里有的。所以这个题就解决了。
int getpow(int n, int k)
{
n = n % mod;
pl[0] = pr[k + 3] = fac[0] = 1;
int ans = 0, y = 0;
for (rint i = 1; i <= k + 2; i++) pl[i] = pl[i - 1] * (n - i) % mod;
for (rint i = k + 2; i >= 1; i--) pr[i] = pr[i + 1] * (n - i) % mod;
for (rint i = 1; i <= k + 2; i++) fac[i] = fac[i - 1] * i % mod;
for (rint i = 1; i <= k + 2; i++)
{
y = (y + qpow(i, k)) % mod;
int a = pl[i - 1] * pr[i + 1] % mod;
int b = fac[i - 1] * ((k - i) & 1 ? -1 : 1) * fac[k + 2 - i] % mod;
ans = (ans + y * a % mod * qpow(b, mod - 2) % mod) % mod;
}
return (ans + mod) % mod;
}
void solve(int x)
{
memset(c, 0, sizeof c);
for (rint i = 2; i * i <= x; i++)
{
if (!(x % i))
{
p[++cnt] = i;
while (!(x % i))
{
x /= i;
c[cnt]++;
}
}
}
if (x > 1) p[++cnt] = x, c[cnt] = 1;
}
void dfs_init(int x, int step)
{
if (x > cnt)
{
int p2 = 1, flag = 1;
for (rint i = 1; i <= cnt; i++)
{
if (t[i] > 1) flag = 0;
else if (t[i] == 1) flag = -flag;
for (rint j = 1; j <= t[i]; j++) p2 *= p[i];
}
if (!flag) return ;
res2 = (res2 + flag * qpow(p2, step) * getpow(n / p1 / p2, step) % mod) % mod;
return ;
}
for (rint i = 0; i <= c[x] - k[x]; i++)
{
t[x] = i;
dfs_init(x + 1, step);
}
}
void solve(int d, int p1, int step)
{
if (d == 1) step = 1;
step++;
int res = qpow(p1, step);
res2 = 0;
dfs_init(1, step);
ans = (ans + res * res2 % mod) % mod;
}
void dfs(int x)
{
if (x > cnt)
{
p1 = 1;
int maxx = 0;
bool flag = 1;
for (rint i = 1; i <= cnt; i++)
{
flag &= (k[i] > 0);
for (rint j = 1; j <= k[i]; j++) p1 *= p[i];
if (k[i]) maxx = max(maxx, (c[i] + k[i] - 1) / k[i]);
}
solve(d, p1, flag ? maxx : 0);
return ;
}
for (rint i = 0; i <= c[x]; i++)
{
k[x] = i;
dfs(x + 1);
}
}
signed main()
{
fac[0] = 1;
for (rint i = 1; i <= 30; i++) fac[i] = fac[i - 1] * i % mod;
int T;
cin >> T;
while (T--)
{
cin >> n >> d;
cnt = ans = 0;
solve(d);
dfs(1);
cout << (ans % mod + mod) % mod << endl;
}
return 0;
}
理性
把式子展开有一个关于 的二次函数:
这个函数的二次项始终为正数,当 取对称轴时函数取到最小值:
代入后得到了一个只与 有关的二次函数, 一定
所以,再让 取对称轴时函数取到最小值
得到了对于一个固定的 , 都已知,所以只要求出 的期望即可。
考虑 。显然有:
直接计算即可。
设状态 分别表示 只考虑前 项的期望,转移方程:
void add(int &x, int y) {x = (x + y) % mod;}
void mul(int &x, int y) {x = x * y % mod;}
int qpow(int a, int b)
{
int res = 1;
while (b)
{
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
int inv(int x){return qpow(x, mod - 2);}
int calc(int x){return x * (x + 1) % mod * (x << 1 | 1) % mod * iv6 % mod;}
int calc(int l, int r) {return (calc(r) - calc(l - 1) + mod) % mod;}
signed main()
{
cin >> n;
for (rint i = 1; i <= n; i++)
{
cin >> d[i] >> l[i] >> r[i];
add(sd, d[i]);
add(sd2, d[i] * d[i] % mod);
}
for (rint i = 1; i <= n; i++)
{
int iv = inv(r[i] - l[i] + 1);
add(ans, calc(l[i], r[i]) * iv % mod);
add(f[i][0] = f[i - 1][0], (l[i] + r[i]) * iv2 % mod);
add(f[i][1] = f[i - 1][1], (l[i] + r[i]) * iv2 % mod * d[i] % mod);
add(f[i][2] = f[i - 1][2], calc(l[i], r[i]) * iv % mod);
add(f[i][2], (l[i] + r[i]) * f[i - 1][0] % mod);
add(f[i][3] = f[i - 1][3], calc(l[i], r[i]) * iv % mod * d[i] % mod);
add(f[i][3], (l[i] + r[i]) * f[i - 1][1] % mod * iv2 % mod);
add(f[i][3], (l[i] + r[i]) * f[i - 1][0] % mod * iv2 % mod * d[i] % mod);
add(f[i][4] = f[i - 1][4], calc(l[i], r[i]) * iv % mod * d[i] % mod * d[i] % mod);
add(f[i][4], (l[i] + r[i]) * f[i - 1][1] % mod * d[i] % mod);
}
int q = inv((n - sd * sd % mod * inv(sd2) % mod + mod) % mod);
add(ans, mod - f[n][4] * inv(sd2) % mod);
add(ans, mod - f[n][4] * qpow(sd * inv(sd2) % mod, 2) % mod * q % mod);
add(ans, mod - f[n][2] * q % mod);
add(ans, 2 * f[n][3] * sd % mod * inv(sd2) % mod * q % mod);
cout << ans << endl;
return 0;
}
本文作者:PassName
本文链接:https://www.cnblogs.com/spaceswalker/p/18158730
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步