和式的变换以及几道例题

和式的变换与推导例题

规则

\(\sum\limits_{k\in K} ca_k=c\sum\limits_{k\in K}a_k\)

\(\sum\limits_{k\in K}(a_k+b_k)=\sum\limits_{k\in K}a_k+\sum\limits_{k\in K}b_k\)

\(\sum\limits_{k\in K}a_k=\sum\limits_{p(k)\in K}a_{p(k)}\) 交换律。\(p(k)\) 是下标排列

和式的变换技术

1. 替换条件式

\(\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{d|\gcd(i,j)}d=\sum\limits_{i=1}^n\sum\limits^m_{j=1}\sum\limits_{d=1}^n[d|i][d|j]d\)

暴力枚举

2. 替换指标变量

\(\sum\limits_{i=1}^n\sum\limits^m_{j=1}[\gcd(i,j)=k]=\sum\limits^n_{ik=1}\sum\limits^m_{jk=1}[\gcd(ik,jk)=k]=\sum\limits^n_{ik=1}\sum\limits^m_{jk=1}[\gcd(i,j)=1]\)

具体证明……

3. 交换求和次序

\(\sum\limits^n_{i=1}\sum\limits^m_{j=1}A(i)B(i)=\sum\limits^m_{j=1}\sum\limits^n_{i=1}A(i)B(i)\)

4. 分离变量

\(\sum\limits^n_{i=1}\sum\limits^m_{j=1}A(i)B(i)=\sum\limits^n_{i=1}A(i)\sum\limits^m_{j=1}B(i)\)

感性理解即可

例题

1#P3455 [POI2007]ZAP-Queries

题意:给出 \(n,m,k\),求 \(\sum\limits_{i=1}^n\sum\limits^m_{j=1}[\gcd(i,j)=k]\)。数据规模 \(1\le k\le n,m\le 5*10^4,T=5*10^4\)

用到莫比乌斯函数的性质 \(\sum\limits_{d|n}\mu(d)=[n=1]\)
此处应用: \([\gcd(i,j)=1]=\sum\limits_{d|\gcd(i,j)}\mu(d)\)

那么

\(\sum\limits_{i=1}^n\sum\limits^m_{j=1}[\gcd(i,j)=1]\\ = \sum\limits_{i=1}^n\sum\limits^m_{j=1}\sum\limits_{d|\gcd(i,j)}\mu(d)\\ =\sum\limits_{i=1}^n\sum\limits^m_{j=1}\sum\limits_{d=1}^n[d|i][d|j]\mu(d)\\ =\sum\limits^n_{d=1}\mu(d)\sum\limits_{i=1}^n[d|i]\sum\limits^m_{j=1}[d|j]\\ =\sum\limits^n_{d=1}\mu(d) \lfloor\dfrac{n}{d}\rfloor \lfloor\dfrac{m}{d}\rfloor\)

算莫比乌斯函数的前缀和,后两项是数论分块。整除分块 \(\sum\limits^n_{i=1}f(i)\lfloor\dfrac{n}{i}\rfloor\)

那么现在再来看复杂情况:

\(\sum\limits_{i=1}^n\sum\limits^m_{j=1}[\gcd(i,j)=k]\\ = \sum\limits_{ik=1}^n\sum\limits^m_{jk=1}[\gcd(ik,jk)=k]\\ =\sum\limits_{i=1}^{\lfloor\dfrac{n}{k}\rfloor}\sum\limits^{\lfloor\dfrac{m}{k}\rfloor}_{j=1}[\gcd(i,j)=1]\)

同理导出莫比乌斯函数,最终

\(\sum\limits_{d=1}^{\lfloor\dfrac{n}{k}\rfloor}\mu(d)\lfloor\dfrac{n}{kd}\rfloor\lfloor\dfrac{m}{kd}\rfloor\)

莫比乌斯函数用线性筛即可。

2#P2257 YY的GCD

题意:给出 \(n,m\)\(\sum\limits^n_{i=1}\sum\limits^m_{j=1}[\gcd(i,j)\in prime]\)

\(\begin{aligned} & \sum_{i=1}^{n} \sum_{j=1}^{m}[\operatorname{gcd}(i, j) \in \text { prim }] \\ = & \sum_{i=1}^{n} \sum_{j=1}^{m} \sum_{k=1}^{n}[\operatorname{gcd}(i, j)=k][k \in \text { prim }] \\ = & \sum_{k=1}^{n} \sum_{i=1}^{\left|\frac{n}{k}\right|} \sum_{j=1}^{\left|\frac{m}{k}\right|}[\operatorname{gcd}(i, j)=1][k \in \text { prim }] \\ = & \sum_{k=1}^{n} \sum_{i=1}^{\left|\frac{n}{k}\right|} \sum_{j=1}^{\left|\frac{m}{k}\right|} \sum_{d \mid \operatorname{gcd}(i, j)} \mu(d)[k \in \text { prim }] \\ = & \sum_{k=1}^{n} \sum_{i=1}^{\left|\frac{n}{k}\right|} \sum_{j=1}^{\left|\frac{m}{k}\right|} \sum_{d=1}^{\left|\frac{n}{k}\right|}[d \mid i][d \mid j] \mu(d)[k \in \text { prim }] \\ = & \sum_{k=1}^{n} \sum_{d=1}^{\left|\frac{n}{k}\right|} \mu(d) \sum_{i=1}^{\left|\frac{n}{k}\right|}[d \mid i] \sum_{j=1}^{\left|\frac{m}{k}\right|}[d \mid j][k \in \text { prim }] \\ =& \sum\limits^n_{k=1}\sum\limits^{\lfloor\frac{n}{k}\rfloor}_{d=1}\mu(d)\left\lfloor\dfrac{n}{kd}\right\rfloor\left\lfloor \dfrac{m}{kd}\right\rfloor\end{aligned}\)

发现无法整除分块,分母是两个变量

\(T=kd\),则 \(d=T/k\)

\(=\sum\limits_{k=1}^{n}\sum\limits_{\frac{T}{k}}^{\left\lfloor\frac{n}{k}\right\rfloor}\mu(\dfrac{T}{k})\left\lfloor\dfrac{n}{T}\right\rfloor\left\lfloor\dfrac{m}{T}\right\rfloor\ [k\in prime] \\ =\sum\limits_{k=1}^{n}\sum\limits_{T=1}^{n}\mu(\dfrac{T}{k})\left\lfloor\dfrac{n}{T}\right\rfloor\left\lfloor\dfrac{m}{T}\right\rfloor\ [k\in prime] \\ =\sum\limits_{T=1}^{n}\left\lfloor\dfrac{n}{T}\right\rfloor\left\lfloor\dfrac{m}{T}\right\rfloor\sum\limits_{k=1}^{n}\mu(\dfrac{T}{k})\ [k\in prime]\\ =\sum\limits_{T=1}^{n}\left\lfloor\dfrac{n}{T}\right\rfloor\left\lfloor\dfrac{m}{T}\right\rfloor\sum\limits_{k\in prime}\mu(\dfrac{T}{k})\)

\(F(T)=\sum\limits_{k\in prime}\mu(\dfrac{T}k)\)

则原式化为:

\(\sum\limits^n_{T=1}F(T)\left\lfloor\dfrac{n}{T}\right\rfloor\left\lfloor\dfrac{m}T\right\rfloor\)

\(F(T)\) 需要预处理

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define LL long long
const int N = 10000010;
int vis[N], p[N], mu[N], cnt;
int F[N];

void init()
{
    mu[1] = 1;
    for (int i = 2; i < N; i++)
    {
        if (!vis[i])
            p[++cnt] = i, mu[i] = -1;
        for (int j = 1; i * p[j] < N; j++)
        {
            vis[i * p[j]] = 1;
            if (i % p[j] == 0)
                break;
            mu[i * p[j]] = -mu[i];
        }
    }
    for (int i = 1; i <= cnt; i++)
        for (int j = p[i]; j < N; j += p[i])
        // j 和 pi 只能是整数倍
            F[j] += mu[j / p[i]];
    for (int i = 1; i < N; i++)
        F[i] += F[i - 1];
}
LL calc(int n, int m)
{
    if (n > m)
        swap(n, m);
    LL ans = 0;
    for (int l = 1, r; l <= n; l = r + 1)
    {
        r = min(n / (n / l), m / (m / l));
        ans += 1ll * (F[r] - F[l - 1]) * (n / l) * (m / l);
    }
    return ans;
}
int main()
{
    init();
    int n, m, T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%d", &n, &m);
        printf("%lld\n", calc(n, m));
    }
}

3#P3327 [SDOI2015] 约数个数和

题意:设 \(d(x)\)\(x\) 的约数个数。给定 \(n,m\)\(\sum\limits^n_{i=1}\sum\limits^m_{j=1}d(ij)\)\(T\) 组询问,\(T,n,m\le 5*10^4\)

结论:\(d(ij)=\sum\limits_{x|i}\sum\limits_{y|j}[\gcd(x,y)=1]\) 证明参考,和数学一本通莫比乌斯反演

证明看不懂,背下来吧。

最后化为 \(\sum\limits^n_{d=1}\mu(d)F(\left\lfloor\dfrac{n}{d}\right\rfloor)F(\left\lfloor\dfrac{m}{d}\right\rfloor)\)

那么预处理 \(\mu\)\(F\),预处理 \(F\) 需要用到一次数论分块,计算结果时还需要用到一次数论分块。

#include <bits/stdc++.h>
#define rei register int
#define ll long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define rep(i, s, n, c) for (register int i = s; i <= n; i+=c)
#define repd(i, s, n, c) for (register int i = s; i >= n; i-=c)
#define CHECK cout<<"WALKED"<<endl;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
#define pb push_back
#define ls id<<1
#define rs id<<1|1
const int INF = INT_MAX;
long long binpow(long long a, long long b, ll mod){long long res = 1;  while (b > 0){if (b & 1) res = res * a % mod;a = a * a % mod;  b >>= 1;  }  return res;}

using namespace std;
const int maxn = 50005;
int vis[maxn], p[maxn], mu[maxn], cnt;
ll F[maxn];
void init()
{
	mu[1]=1;
	rep (i, 2, maxn - 1, 1) {
		if (!vis[i]) {
			p[++cnt] = i;
			mu[i]= -1;
		}
		for (int j = 1; i * p[j] < maxn; j++) {
			vis[i * p[j]] = 1;
			if (i % p[j] == 0) break;
			mu[i * p[j]] = -mu[i];
		}
	}
	rep (i, 1, maxn - 1, 1) {
		mu[i] += mu[i - 1]; // mobius prefixsum
	}
	rep (i, 1, maxn - 1, 1) {
		int r;
		rep(l, 1, i, -l + r + 1) {
			r = (i / (i / l));
			F[i] += 1ll * (r - l + 1) * (i / l);
		}
	}
}
ll cc(int n, int m)
{
	if (n > m) swap(n, m);
	ll ans = 0;
	int r;
	rep (l, 1, n, -l + r + 1) {
		r = min(n / (n / l), m / (m / l));
		ans += (mu[r] - mu[l - 1]) * F[n/l] * F[m/l];
		// 下标整除也可以分块
	}
	return ans;
}
int main()
{
	init();
	int n, m, T = read();
	while (T--) {
		n = read(), m = read();
		printf("%lld\n", cc(n,m));
	}
    return 0;
}

最后整理一下

待做题目:P2522

posted @ 2022-12-30 17:20  Vegdie  阅读(306)  评论(0编辑  收藏  举报