简单数学题乱写

数学


数论分块:

结论:整除分块是用于快速处理形似 \(\sum _ {i=1} ^n \lfloor \dfrac n i\rfloor\)​ 的式子的办法,对于这玩意通过严谨的数学推理(打表) 我们发现实际上这些取值是连续且有规律的,即

如果一个值的开始位置时为 \(l\) 那么它的结束位置 \(r\) 就是 \(\lfloor \dfrac n {\lfloor \frac n l \rfloor} \rfloor\)

引理1

\[\forall a,b,c \in Z,\lfloor \dfrac a {bc} \rfloor =\lfloor \dfrac{\lfloor \frac a b \rfloor} c \rfloor \]

证明略

引理2

对于一个较大的 \(n\) 我们显然会发现,我们后面的这个下取整取值并不是每一次都随着 \(i\) 而变化的,它是呈块状分布的,同时这个下取整的值我们也能得到,应该是共有 \(2\sqrt n\) 个值

结论

通过严谨的数学推理(打表) 我们发现实际上这些取值是有规律的,即

如果一个块的开始位置时 \(l\) 那么它的结束位置 \(r\) 就是 \(\lfloor \dfrac n {\lfloor \frac n l \rfloor} \rfloor\)


P2261 [CQOI2007]余数求和

给定正整数 \(n\)\(k\),请计算

\[G(n,k) = \sum_{i = 1} ^n k \bmod i \]

对于这个题来说,我们首先考虑把 \(k \bmod i\) 拆开 \(k-\lfloor \dfrac k i \rfloor*i\)

那么 \(k\) 肯定不用管,原式先把 \(k\) 提出来 \(kn-\sum _{i=1}^n \lfloor \dfrac k i \rfloor*i\)

后面的东西就可以用我们说的数论分块了

时间复杂度据说是 \(O(\sqrt k)\)

ll ans = n * k;
for (int l = 1, r = 0; l <= n; l = r + 1)  {
    if (k / l) r = min(k / (k / l), n);
    else r = n;
    ans -= (k / l) * (r - l + 1) * (l + r) / 2;
}

P2260[清华集训2012]模积和

\[计算:~\sum _{i = 1} ^ n\sum_{j=1}^m(n\bmod i)\times (m\bmod j),i \not = j \]

\(i\not = j\) 看着就不爽,我们先容斥一下,把它拆开

\[\sum_{i=1}^n\sum_{j=1}^m(n\bmod i) \times (m \bmod j) - \sum_{i=1}^{\min(m,n)} (n\bmod i)\times (m\bmod i)\\ \]

两边分开讨论处理,首先左边看起来 \(n\bmod i\)\(j\) 没啥关系,我们先提出来

\[\sum_{i=1} ^ n(n\bmod i) \sum _{j=1}^m (m\bmod j)=\sum_{i=1}^n(n-\lfloor \dfrac n i\rfloor\times i)\sum_{j=1}^m(m-\lfloor \dfrac m j \rfloor\times j) \]

然后我们把 \(n,m\) 提出来

\[=(n^2-\sum_{i=1}^ni\times\lfloor \dfrac n i\rfloor)\times(m^2-\sum_{i=1}^mj\times\lfloor \dfrac m i\rfloor) \]

左右两边可以分别进行整除分块

然后我们考虑右边,同同样的方式

\[\sum_{i=1}^{\min(m,n)}(n-\lfloor \dfrac n i \rfloor\times i) \times (m - \lfloor \dfrac m i\rfloor\times i) =\sum_{i=1}^n(nm-\lfloor \dfrac n i\rfloor\times i\times m-\lfloor \dfrac m i \rfloor \times i\times n+\lfloor \dfrac n i\rfloor \lfloor \dfrac m i\rfloor\times i^2) \]

对于 \(\dfrac n i\)\(\dfrac m i\) 我们可以一起处理,大不了多分几块

就是对于后面的 \(i^2\) 得想个办法前缀和处理一下

于是我们就有

\[1^2+2^2+3^2\dots+n^2=\dfrac {n(n+1)(2n+1)} 6\\ \]

所以前面的东西我们也就可以预处理了

前面的前缀和公式证明如下:

\(f(x)\) 表示 \(x^3-(x-1)^3\)

我们计算

\[\sum_{i=1}^n f(i) \]

于是

\[f_x=x^3-(x-1)^3=x^3-(x^3-3x^2+3x-1)=3x^2-3x+1\\ \sum_{i=1}^nf(i)=3\sum_{i=1}^ni^2-3\sum_{i=1}^ni+n \]

又由定义可知:\(f(x)=x^3-(x-1)^3\)

所以

\[\sum_{i=1}^nf(i)=n^3 \]

所以我们把两个式子联立一下就有

\[3\sum_{i=1}^ni^2-3\sum_{i=1}^ni+n=n^3\\ 3\sum_{i=1}^ni^2=n^3+3\sum_{i=1}^ni-n\\ 3\sum_{i=1}^ni^2=n^3+\dfrac {3n\times (n+1)}2-n=\dfrac {2n^3+3n^2+n} 2=\dfrac {n(n+1)(2n+1)} {2}\\ \sum_{i=1}^ni^2=\dfrac {n(n+1)(2n+1)} {6} \]

最后让我尽可能的独立写出一份代码!

read(n, m);
if (n > m) swap(n, m);

tmp = n * n % mod;
for (int l = 1, r; l <= n; l = r + 1) {
    if (n / l) r = min(n / (n / l), n);
    else r = n; 
    tmp = (tmp - (n / l) * ((l + r) * (r - l + 1) / 2 % mod) % mod + mod) % mod;
}
ans = tmp;
tmp = m * m % mod;
for (int l = 1, r; l <= m; l = r + 1) {
    if (m / l) r = min(m / (m / l), m);
    else r = m;
    tmp = (tmp - (m / l) * ((l + r) * (r - l + 1) / 2 % mod) % mod + mod) % mod;
} 
ans = ans * tmp % mod;

tmp = 0;
for (int l = 1, r; l <= n; l = r + 1) {
    if (n / l) r = min(n / (n / l), n);
    else r = n; 
    tmp = (tmp + (n / l) * ((l + r) * (r - l + 1) / 2 % mod) % mod) % mod;
}

tmp = tmp * m % mod;
ans = (ans + tmp) % mod;
tmp = 0;

for (int l = 1, r; l <= n; l = r + 1) {
    if (m / l) r = min(m / (m / l), n);
    else r = n;
    tmp = (tmp + (m / l) * ((l + r) * (r - l + 1) / 2 % mod) % mod + mod) % mod;
}
tmp = tmp * n % mod;
ans = (ans + tmp) % mod;
ans = ((ans - n * n % mod * m % mod) % mod + mod) % mod;
tmp = 0;
for (int l = 1, r; l <= n; l = r + 1) {
    if (n / l) r = min(n / (n / l), m / (m / l));
    else r = n;
    tmp = ((tmp + (n / l) * (m / l) % mod * (sum(r) - sum(l - 1)) % mod) % mod + mod) % mod;
}
ans = (ans - tmp) % mod + mod;
write(ans % mod, '\n');
return 0;
}
//write:RevolutionBP

顺便压缩了一下,应该这个长度的比较合适

inline int sum(int x) {
    return x * (x + 1) % mod * (2 * x + 1) % mod * 3323403 % mod;
}

int left1, left2;
int right1, right2, right3;
signed main(){
#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    read(n, m);
    if (n > m) swap(n, m);
    left1 = n * n % mod;
    left2 = m * m % mod;
    for (int l = 1, r; l <= n; l = r + 1) {
        if (n / l) r = min(n, n / (n / l));
        else r = n;
        left1 = (left1 - (n / l) * ((l + r) * (r - l + 1) / 2 % mod) % mod + mod) % mod;
        right1 = (right1 + (n / l) * ((l + r) * (r - l + 1) / 2 % mod) % mod) % mod;
    }

    for (int l = 1, r; l <= m; l = r + 1) {
        if (m / l) r = min(m, m / (m / l));
        else r = m;
        left2 = (left2 - (m / l) * ((l + r) * (r - l + 1) / 2 % mod) % mod + mod) % mod;
    }

    for (int l = 1, r; l <= n; l = r + 1) {
        if (n / l) r = min(n / (n / l), m / (m / l));
        else r = n;
        right2 = (right2 + (m / l) * ((l + r) * (r - l + 1) / 2 % mod) % mod) % mod;
        right3 = ((right3 + (n / l) * (m / l) % mod * ((sum(r) - sum(l - 1)) % mod + mod) % mod) % mod + mod) % mod;
    }
    right1 = right1 * m % mod;
    right2 = right2 * n % mod;
    tmp = left1 * left2 % mod;
    ans = (tmp - (n * n % mod * m % mod - (right1 + right2 - right3) % mod) % mod + mod) % mod;
    write((ans + mod) % mod, '\n');
    return 0;
}

P3935 Calculating

\(x\) 分解质因数结果为 \(p_1^{k_1} p_2^{k_2}\dots p_n^{k_n}\),令 \(f(x)=(k_1+1)(k_2+2)\dots(k_n+1)\),求

\[\sum_{i=l}^rf(i) \]

首先我们肯定得容斥一下

\[\sum_{i=1}^rf(i)-\sum_{i=1}^{l-1} f(i) \]

然后我们去观察 \(f(x)\) 的定义发现其实就是因数个数,所以我们考虑改变思考方式,对于 \(1\sim n\) 的因数个数之和,我们可以转化成统计一个因数在哪些数中出现过

所以原题就很简单了,我们枚举每一个数,计算一下 \(\lfloor \dfrac n i\rfloor\),那么最终答案就应该是

\[\sum_{i=1}^n \lfloor \dfrac n i \rfloor \]

直接整除分块即可


线性筛

P2158 [SDOI2008] 仪仗队

作为体育委员,C 君负责这次运动会仪仗队的训练。仪仗队是由学生组成的 \(N \times N\) 的方阵,为了保证队伍在行进中整齐划一,C 君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。

现在,C 君希望你告诉他队伍整齐时能看到的学生人数。

首先第一步我们转化题意,如果存在一个队员我们看不见,那么它的 \(\gcd(x,y)\) 必定 \(>1\)

原因很简单,因为如果我们出现了一个点它的 \(g=\gcd \not = 1\) 则有一个必然的现象就是 \(x/g,y/g\) 这个点会挡住它

所以题意就转化成了给定你一个 \(n * n\) 区间,问你其中有多少个坐标互质

我们考虑若 \((i,j)\) 这个点满足条件,则 \((j,i)\) 必然也满足条件,所以我们直接统计 \(j<i\) 的情况,最后再乘上 \(2\) 即可

我们固定住 \(i\) 考虑这一行有多少个与 \(i\) 互质,由于 \(j<i\) 所以这就是欧拉函数 \(\varphi\) 的定义

复习一下欧拉筛:

我们求 \(\varphi(k)\)时,当 \(k\) 是质数时,显然 \(\varphi(k) = k-1\)

\(k\) 不是质数时:
分开考虑

我们已知

\[\varphi(N)= N*(1-\frac{1}{p_1})*(1-\frac{1}{p_2})\dots \]

我们枚举到 \(i\)

\(i \mid k\),且 \(i\) 为质数,则我们有 \(\varphi(i*k)=\varphi(k)*i\) 原因是 \(i\) 已经是一个质因子了,它对于里面的那堆玩意乘起来没有作用,只是让 \(N\) 翻了个倍,

\(i\nmid k\),且 \(i\) 为质数,则我们有 \(\varphi(i\times k)= \varphi(k) \times (i-1)\)

\[ \varphi(i \times k)=i \times k \times (1-\frac{1}{p_1}) \times (1-\frac{1}{p_2})\dots \times (1-\frac{1}{p_n}) \times (1-\frac{1}{i})\\ \varphi(k)=k \times (1-\frac{1}{p_1}) \times (1-\frac{1}{p_2})\dots \times (1-\frac{1}{p_n})\\ \]

因此我们发现,上面除以下面以后

\[ \varphi(i \times k) = i \times (1 - \dfrac {1} {i}) \varphi(k)=(i-1) \times \varphi(k) \]

然后我们把线性筛写出来

inline void get_prime() {
    rep (i, 2, N - 1) {
        if (!st[i]) {
            prime[++cnt] = i;
            continue;
        }
        rep (j, 1, cnt) {
            if (prime[j] * i > N - 1) break;
            st[prime[j] * i] = true;
            if (i % prime[j] == 0) break;
        }
    }
}

我们观察这一段代码,看看如何把上面的三条性质代入求得 \(\varphi\) 数组

首先比较容易的是当 \(k\) 为质数时,我们直接在 if(!st[i]) prime[++cnt] = i 的地方 后面加一句 phi[i] = i - 1

然后第二条性质的话要求整除,我们可以利用 i % prime[j] == 0 时,\(prime_j\)\(i\) 的最小质因子的性质,后面加一句 phi[i * prime[j]] = phi[i] * prime[j]

第三条的性质的话,我们就可以在最后放上一句 phi[i * prime[j]] = (i - 1) * prime[j]

那么完整代码如下:

inline void get_phi() {
    phi[0] = phi[1] = 1; //注意这里的 phi[1] 定义为 1
    rep (i, 2, n) {
        if (!st[i]) prime[++cnt] = i, phi[i] = i - 1;
        for (int j = 1; j <= cnt and prime[j] * i <= n; j++) {
            st[i * prime[j]] = true;
            if (i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            phi[i * prime[j]] = phi[i] * (prime[j] - 1);
        }
    }
} 

所以这题我们也就可以轻松的解决了

read(n);
n --;
if (!n) return write(0, '\n'), 0;
get_phi();
rep (i, 1, n)
    ans += phi[i];
write(ans << 1 | 1, '\n');

P4626 一道水题 II

求一个能被 \([1,n]\) 内所有数整除的最小数字,并对 \(1e8+7\) 取模

数据范围:\(1\le n \le 10^8\)

首先第一步我们转化题意,对于一个区间内都整除的数,应该就是他们的最小公倍数

我们接下来考虑怎么做这个玩意

首先我们肯定知道,一堆数的最小公倍数应该是等于

\[\prod_{i=1} ^{k} p_i^{\max{k_i}} \]

那么我们就要找到每一个质因子的最高次项

首先对于一个小于 \(\sqrt n\) 的数,我们的 \(k_i\) 必然是 \(\lfloor \log_{x_i}n \rfloor\)

对于一个大于 \(\sqrt n\) 的数,我们的 \(k_i\) 就是 1
所以我们直接开始筛质数,然后小于 \(\sqrt n\) 的我们算一下贡献,大于的我们再算一下就行

但是这里的数据卡的很紧,我们每次算 \(\log\) 的话可能会 TLE

我们用一下换底公式

\[\log _x y=\dfrac {\log_k y} {\log_k x} \]

\(k=2\) 则我们上面的 \(\log _{x_i} n\) 就等于 \(\dfrac {\log_2 n} {\log_2 {x_i}}\)

inline void get_prime(int n) {
    limit = sqrt(n);
    rep (i, 2, n) {
        if (!st[i]) {
            prime[++cnt] = i;
            if (i <= limit) ans = ans * 1ll * ksm(i, log2(n) / log2(i)) % mod;
            else ans = ans * 1ll * i % mod;
        }
        for (int j = 1; j <= cnt and prime[j] * i <= n; j++) {
            st[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}

int main(){
    read(n);
    get_prime(n);
    write(ans, '\n');
    return 0;
}
//write:RevolutionBP

CF1017F The Neutral Zone

定义 \(exlog_f(p_1^{\alpha_1}p_2^{\alpha_2}\dots p_n^{\alpha_n})= >\alpha_1f(p_1)+\alpha_2 f(p_2)\dots \alpha_nf(p_n)\)

\(f(x) = Ax^3+Bx^2+Cx+D\)
\(\sum_{i=1}^n exlog_f(i)\)
空间限制: 16MB 时间限制:5s
结果对 \(2^{32}\) 取模

取模的问题很好解决,开 \(unsigned~int\) 即可

对于 \(exlog_f(p_1^{\alpha_1}p_2^{\alpha_2}\dots p_n^{\alpha_n})\) 我们可以发现,\(exlog_f(a \times b) = exlog_f(a)+exlog_f(b)\)

原因不用多说,因此我们考虑原问题可以被搞成

\[exlog_f(n!) \]

这玩意我们考虑对于 \(n!\) 来说我们很容易得到它的质因子的指数即 \(p_i\) 的指数为

\[ \sum_{i=1}^{\infty} \lfloor \dfrac {n} {p_i} \rfloor \]

这个证明就不必要了

那么答案我们就可以表示为

\[exlog_f(n!) = \sum_{x\in prime} ^ n (f(x) \times \sum _{i=1} ^ {\infty} \lfloor \dfrac n {x^i} \rfloor ) \]

这样的写法时间复杂度大概在 \(O(n)\)

但是我们这样写的空间复杂度大概为 \(286MB\)

我们考虑,其实我们如果要是用埃筛呢?

这就给了我们很大的启示,我们可以把原来的 \(n\) 拆成很多段,这样的话,每一段内部我们可以用区间筛法搞掉

同时这样的话,我们不需要筛到 \(n\),只需要筛到 \(\sqrt n\) 即可

这样算下来的话我们的空间复杂度很小,只有 \(O(\sqrt n + B)\),B是块长
但是同样时间复杂度就有点高可能会达到 \(O(n\log \log \sqrt n)\)
但是还是肯定能过的

这道确实是一道好题啊!!!

int n, blo, ans, a, b, c, d, cnt, prime[2100];
bool st[17322];

inline int F(int x) {
    return a * x * x * x + b * x * x + c * x + d;
}

inline int calc(int x) {
    int k = 0, y = n / x;
    while (y) {
        k += y;
        y /= x;
    }
    ans += k * F(x);
    return ans;
}
inline void get_prime() {
    rep(i, 2, blo) {
        if (!st[i])
            prime[++cnt] = i, calc(i);
        for (int j = 1; j <= cnt and prime[j] * i <= blo; j++) {
            st[prime[j] * i] = true;
            if (i % prime[j] == 0)
                break;
        }
    }
}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    read(n, a, b, c, d);
    blo = sqrt(n);
    get_prime();
    int l = 1, r = blo;
    while (r < n) {
        l = r + 1, r = min(r + blo, n);
        rep(i, l, r)
            st[i - l + 1] = true;
        rep(i, 1, cnt) {
            for (int j = (l + prime[i] - 1) / prime[i] * prime[i]; j <= r; j += prime[i])
                st[j - l + 1] = false;
        }
        rep(i, l, r) if (st[i - l + 1]) calc(i);
    }
    write(ans, '\n');
    return 0;
}
// write:RevolutionBP

P6810 「MCOI-02」Convex Hull 凸包

\[\sum_{i=1}^n\sum_{j=1}^md(i)d(j)d(\gcd(i,j)) \]

其中 \(d(x)\) 表示 \(x\) 的约数个数
\(1 \le n,m \le 2\times 10^6~~~~~\)\(1\le p \le 10^9\)

这个题基本上就是自己独立完成的
直接推两个式子即可

\[\sum_{i=1}^n\sum_{j=1}^md(i)d(j)\sum_{k\mid i\&k\mid j} 1\\ \sum_{k=1}^{\min(n,m)}\sum_{k\mid i}^n d(i) \sum_{k\mid j}^m d(j) \]

inline void get_d(int n) {
    rep (i, 1, n)
        for (int j = i; j <= n; j += i)
            d[j]++;
}
inline int calc(int n, int k) {
    int res = 0;
    for (int i = k; i <= n; i += k) res = (res + d[i]) % p; 
    return res;
}
int main(){
    read(n, m, p);
    if (n > m) swap(n, m);
    get_d(m);
    rep (i, 1, n) ans = (ans + 1ll * calc(n, i) * calc(m, i) % p) % p;
    write(ans, '\n');
    return 0;
}
//write:RevolutionBP

莫比乌斯反演

基本形式:

\[\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)==1]=\sum_{x=1}^n\mu(x)\lfloor \dfrac n x \rfloor \lfloor \dfrac m x \rfloor \\ gcd(i,j)==1 \iff \sum_{d\mid (i,j)}\mu(d) \]

posted @ 2022-03-10 22:33  RevolutionBP  阅读(91)  评论(0编辑  收藏  举报