【长期】数论题
题单:
注意到当 \(i=l\) 时,有 \(val=\left\lfloor\dfrac n l\right\rfloor\)。假设当 \(i=r\) 时值仍然为 \(val\),则有 \(val=\left\lfloor\dfrac n r\right\rfloor\),\(val\le \dfrac n r<val+1\),\(r\le \dfrac n {val}\) 且 \(r\) 为整数。
因此,当 \(l\le i\le \lfloor\dfrac n {\left\lfloor\frac n l\right\rfloor}\rfloor\) 时 \(val\) 相等。可以证明,这样的值不超过 \(\sqrt n\) 个,因此时间复杂度 \(O(\sqrt n)\)。
本题考查取模运算的本质。\(k\bmod i\) 相当于 \(k-\left\lfloor\dfrac k i\right\rfloor\times i\),因此本题式子可以化为:
这同样可以使用整除分块求解,辅以等差数列求和即可,即每次累加
同样地,我们来看 \(\text{wod}\) 运算的本质。实际上 \(N \text{wod}\ i= \left\lceil\dfrac N i\right\rceil\times i-N\)。不妨设 \(n\le m\),则原式可以化为
我们将前后两部分分别记为 \(A,D\) 并分开计算:
其中上取整同样可以用整除分块在根号的时间复杂度下计算:
现在需要对 \(val-1\) 分类讨论。
- 如果 \(val=1\),那么 \(r=n\),即直接取到右端点;
- 如果 \((val-1)|n\),那么 \(r=\dfrac{n}{val-1}-1\)
- 否则 \(r=\lfloor\dfrac n {val-1}\rfloor\)
将 \(A\) 中 \(n,m\) 两部分分开计算即可,时间复杂度 \(O(\sqrt n)\)。
又
这个式子同样可以用整除分块计算,其中还需要平方和公式的前缀和做差
由于在模意义下计算,需要算出 \(2,6\) 等的逆元,在不保证模数是质数的情况下使用 exgcd 即可。最后输出时,由于是 \(\text{wod}\ k\),等价于 (mod - ans%mod) % mod 语句,中途使用正常的 %mod 即可。
inline ll work(ll lim, ll num) {
ll res = 0;
for(ll l = 1, r = 1; l <= lim; l = r + 1) {
ll val = ceil(num * 1.0 / l);
if(val == 1) r = lim;
else if(num % (val - 1) == 0) r = num / (val - 1) - 1;
else r = num / (val - 1);
r = min(r, lim);
ll sum = ((inv2 * (l + r) % mod) * (r - l + 1) % mod);
res = (res + val * sum % mod) % mod;
}
return res;
}
inline ll Square(ll x) {return (((inv6 * x % mod) * (x + 1) % mod) * (2 * x + 1)) % mod;}
inline ll rSum(ll x, ll y) {return ((Square(y) - Square(x - 1)) % mod + mod) % mod;}
inline void solve() {
read(T);
while(T --) {
read(n); read(m); read(mod); if(n > m) n ^= m ^= n ^= m; inv2 = inv(2); inv6 = inv(6);
ll ans = 0; ll n2 = ((n % mod) * n % mod), m2 = ((m % mod) * m % mod);
ll M1 = ((work(n, n) - n2) % mod + mod) % mod;
ll M2 = ((work(m, m) - m2) % mod + mod) % mod;
ans = M1 * M2 % mod;
ll D = n2 * m % mod;
D = ((D - n * work(n, m) % mod) % mod + mod) % mod;
D = ((D - m * work(n, n) % mod) % mod + mod) % mod;
ll res = 0;
for(ll l = 1, r = 1; l <= n; l = r + 1) {
ll val1 = ceil(n * 1.0 / l), val2 = ceil(m * 1.0 / l);
ll rn = 0, rm = 0;
if(val1 == 1) rn = n;
else if(n % (val1 - 1) == 0) rn = n / (val1 - 1) - 1;
else rn = n / (val1 - 1);
if(val2 == 1) rm = n;
else if(m % (val2 - 1) == 0) rm = m / (val2 - 1) - 1;
else rm = m / (val2 - 1);
rm = min(rm, n);
r = min(rn, rm); ll sum = rSum(l, r);
res = (res + (val1 * val2 % mod) * sum % mod) % mod;
}
D = (D + res) % mod;
ans = ((ans - D) % mod + mod) % mod; ans = (mod - ans) % mod;
writeln(ans);
}
}
P3935 约数个数和
题目中的 \(f(n)=\tau(n)\) 表示约数个数,因此此题求得是
枚举约数,并利用前缀和做差计算区间和即可,因此下面计算前缀和。
用整除分块计算即可,时间复杂度 \(O(\sqrt n)\)
转化成平面直角坐标系,除了 \((1,0),(0,1)\) 两个点之外,其余点 \((i,j), i,j\in [1,N)\) 有连线当且仅当 \(\gcd(i,j)=1\),否则会被点 \((\dfrac i {\gcd(i,j)},\dfrac j {\gcd(i,j)})\) 挡住。
因此,答案为
这道题是一道筛法练习题。
题目中要求 \(\tau(n)=p_1\times p_2\),定义 \(\omega(n)\) 表示去重前 \(n\) 的质因数个数,\(\text{lpf}(n)\) 表示 \(n\) 的最小质因数大小,即 \(\text{least prime factor}\)。
这两个函数都可以在线性筛的时候计算,其中
这样计算出 \(\omega\) 的问题在于当 \(i=prime_j\) 时 \(\omega(p^2)=2\),所以判断的条件是 \(\omega(\tau(x))=2\ \and\ \tau(x)\neq\text{lpf}(\tau(x))^2\)
inline void init(int MAX) {
vis[1] = vis[0] = 1;
tau[1] = 1, w[1] = lpf[1] = 0;
rep(i, 2, MAX) {
if(!vis[i]) prime[++cnt] = i, tau[i] = 2, w[i] = 1, lpf[i] = i;
for(int j = 1; j <= cnt && i * prime[j] <= MAX; j ++) {
w[i * prime[j]] = w[i] + 1;
vis[i * prime[j]] = 1;
lpf[i * prime[j]] = min(lpf[i], prime[j]);
if(i % prime[j] == 0) {
tau[i * prime[j]] = tau[i] * 2 - tau[i / prime[j]];
break;
}
tau[i * prime[j]] = tau[i] * 2;
}
}
}
int main () {
init(1000000), int k = 0;
rep(i, 1, 1000000) {
if(w[tau[i]] == 2 && tau[i] != lpf[tau[i]] * lpf[tau[i]])
if(++k == 9) k = 0, writeln(i);
}
return 0;
}

浙公网安备 33010602011771号