[BZOJ4833]最小公倍佩尔数
在文化课晚自习想出来的奇怪玩意儿。
Description
令 \((1+\sqrt{2})^n=e(n)+\sqrt{2}f(n)\),其中 \(e(n),f(n)\) 都是整数,显然有 \((1-\sqrt{2})^n=e(n)-\sqrt{2}f(n)\)。令 \(g(n)=\operatorname{lcm}(f(1),f(2),\dots,f(n))\)。
给定两个正整数 \(n,p\),其中 \(p\) 是质数,并且保证 \(f(1),f(2),\dots,f(n)\) 在模 \(p\) 意义下均不为 \(0\),请计算 \(\sum \limits_{i=1}^n i\times g(i)\) 模 \(p\) 的值。
Analysis
先定义一些简化运算的符号:\(f(T)=\{f(x) | x \in T\}\),\(\gcd(T)\) 表示 \(T\) 中所有元素的最大公因数,\(\dfrac{T}{d}=\left\{\left.\dfrac{x}{d}\right|x \in T\right\}\),\(d|T\) 表示是否所有 \(T\) 中元素均为 \(d\) 的倍数。
先从题目直接给出的条件入手可以得到 \(f(n)\) 的通项公式:\(2\sqrt2f(n)=(1+\sqrt2)^n-(1-\sqrt2)^n\)。
然后发现一个常见的数列性质:\(x|y \Rightarrow f(x)|f(y)\)。证明可以使用因式定理。
令 \(kx=y\),则只需说明 \((1+\sqrt2)^x-(1-\sqrt2)^x|(1+\sqrt2)^{kx}-(1-\sqrt2)^{kx}\)。
令 \(a=(1+\sqrt2)^x,b=(1-\sqrt2)^x\),即证 \(a-b|a^k-b^k\),显然成立。
结果发现必要性着证不了,这虽然也不知道他是不是充要条件,也不用管了。
假如这是充要条件,那么就一定有 \(\gcd(f(T))=f(\gcd(T))\)。
令 \(S=[1,n]\cap \Z\),则
于是完全可以把 \(T\) 的枚举移到指数上去。
现 f(d) 已经简单到到极致了,只考虑指数优化,发现特别可以莫比乌斯反演。
后面这一坨仔细想想,\([dk|T]\) 实际上限制了 \(T\) 的元素取值范围必须为 \(dk\) 的倍数,在 \(dk\) 确定后 \(T\) 的元素种数也就确定了,这就特别爽。易知后面这一大坨相当于 \([dk\leq n]\),值显然为 \(1\)。
所以最后的式子是 \(\displaystyle \prod_{d=1}^nf(d)^{\sum _{k=1}^{n/d} \mu(k)}\)。
直接预处理 \(\mu(k)\) 前缀和 \(\mu'(k)\) 就……可以了吗?
他不是只求一个 \(g(n)\),而是要求 \(n\) 个 \(g(i)\)。但这样做单次复杂度是 \(\mathcal O(n)\) 的。
固定 \(d\),\(\lfloor\dfrac{i}{d}\rfloor\) 随着 \(i\) 的增大变化次数总共只有 \(\dfrac{n}{d}\) 次,枚举 \(d\) 再枚举这几次变化,就是调和级数复杂度 \(\mathcal O(n\log n)\)。
Solution
具体就实现一个差分,这里修改了过后会影响后面的 \(g(i)\),最后前缀积一下就行了。
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define per(i, r, l) for (int i = r; i >= l; --i)
#define LL long long
#define ULL unsigned long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define eb emplace_back
#define MOD(x) ((x) >= mod ? (x)-mod : (x))
#define FASTIO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;
const int N = 1e6+5;
int n, mod, p[N], m;
inline LL qpow(LL a, int b, LL res = 1) {
for (; b; b >>= 1, a=a*a%mod) if (b&1) res = res*a%mod;
return res;
}
bool v[N];
LL mu[N];
inline void prework(int n) {
mu[1] = 1;
for (int i = 2; i <= n; ++i) {
if (!v[i]) p[++m] = i, mu[i] = -1;
for (int j = 1; j <= m && p[j]*i <= n; ++j) {
v[i*p[j]] = 1, mu[i*p[j]] = -mu[i];
if (i % p[j] == 0) {
mu[i*p[j]] = 0;
break;
}
}
}
}
LL f[N], c[N], inv[N];
inline LL calc(int x, int op) {
if (op==0) return 1;
if (op < 0) return inv[x];
return f[x];
}
inline void solve() {
cin >> n >> mod; f[1] = c[1] = 1;
for (int i = 2; i <= n; ++i) f[i] = ((f[i-1]<<1)+f[i-2])%mod, c[i] = 1, inv[i] = qpow(f[i], mod-2);
for (int d = 2; d <= n; ++d)
for (int i = 1; i*d <= n; ++i)
(c[i*d] *= calc(d, mu[i])) %= mod;
LL ans = 1;
for (int i = 2; i <= n; ++i) c[i] = c[i-1]*c[i]%mod, ans = (ans+c[i]*i)%mod;
cout << ans << '\n';
}
signed main() {
FASTIO;
int _;
cin >> _;
prework(1e6);
while (_--) solve();
return 0;
}
补充
前边假设了一个结论 \(x \mid y \Leftrightarrow f(x)\mid f(y)\)。现在来证明。
充分性已经证过了。
必要性考虑证明 \(x \nmid y \Rightarrow f(x) \nmid f(y)\)。
假设 \(y=kx+r(k\in \N,0<r<x)\)。
即证 \((1+\sqrt 2)^x-(1-\sqrt 2)^x \nmid (1+\sqrt 2)^{kx+r}-(1-\sqrt 2)^{kx+r}\)。
令 \(a=(1+\sqrt 2)^x,b=(1-\sqrt 2)^x\)。
要证 \(a-b \nmid a^k(1+\sqrt 2)^r-{b^k}(1-\sqrt 2)^r\),只需证明 \(a-b\) 不是右式的因式即可。
反证法,假设 \(a-b\) 是右式的因式,则根据因式定理,\(a=b\) 时,右式为 \(0\),即 \(a^k(1+\sqrt 2)^r-b^k(1-\sqrt 2)^r=0\),进一步地,\((1+\sqrt 2)^r-(1-\sqrt 2)^r=0\),显然在 \(r\in(0,x)\) 时不可能成立,所以矛盾了!。
对于广义斐波那契数列 \(f_{n+1}=af_n+bf_{n-1}\) 上面那个结论其实是一个普遍性质。
通过这个结论可以导出:\((f_a,f_b)=f_{(a,b)}\) 和 \([f_a,f_b]=f_{[a,b]}\)(不常用)。

浙公网安备 33010602011771号