Dirichlet 前缀和
P5495 Dirichlet 前缀和 题意
求
其中
分析
我们考虑从高维点的角度来看。
建立一个以质数为维度的坐标系,由于每一个数都能被拆为唯一形式的质数积,它们在坐标系中都有对应的点。
如 \(6\) 能被拆为 \(2^1 \times 3^1\) ,在 \(2-3\) 的坐标系中,坐标即为 \((1,1)\) 。
考虑高维前缀和,先上代码:
for(int i=1;i<=cnt;i++)
for(int j=1;prime[i]*j<=n;j++)
F[prime[i]*j]+=F[j];
乍一看可能根本看不懂,但你得一步步来分析。
首先明确一点,在坐标系中,如果有一个正整数 \(a\) ,它的每一个坐标值都不大于另一个正整数 \(b\) 的对应每一个坐标值。
那么将 \(a\) 和 \(b\) 拆开来, \(a\) 的每一个质因子次数都不大于 \(b\) 的每一个质因子次数。
显然 \(a\) 是 \(b\) 的约数,反过来,\(b\) 当然也是 \(a\) 的倍数。
再回过头来看一下代码:
for(int i=1;i<=cnt;i++)
for(int j=1;prime[i]*j<=n;j++)
F[prime[i]*j]+=F[j];
第一层循环显然是在枚举每一个质数,即每一个维度,
然后由第二层循环,在当前这一维度给它从小到大做前缀和。
因为是当前这一质数的维度,所以在你给这一个数乘上一个当前质数时,这个数的当前坐标值才会 \(+1\) 。
似这样,在每一维度都做一遍前缀和,最终 \(F'(n)\) 就等于所有坐标值都小于它的所有 \(F\) 的和,即为它的所有约数的 \(F\) 值的和。
形式化的,写作
显然,\(F'\) 数组即为所求,按题目要求,将其全部异或输出即可。
P2714 四元组统计 题意
有 \(n\) 个正整数 \(a_i\),你要统计有多少个四元组满足 \(gcd(a_i,a_j,a_k,a_l) = 1\)。
其中 \(4 \le n \le 10000 ,1 \le ai \le 10000\) ,且数据组数不超过 \(100\).
分析
同上题,考虑高维后缀和,使得 \(F'(n)= \sum \limits_{n|T} F(T)\) .
再令 \(F'(n)=F(n) \times (F(n)-1) \times (F(n)-2) \times (F(n)-3) \times \frac{1}{24}\)
使得 \(F(n)\) 等于公约数有 \(n\) 的四元组的个数。
再做高维差分,减去公约数为 \(n\) 的倍数的方案数,使得 \(F(n)\) 等于最大公约数为 \(n\) 的四元组的个数, \(F(1)\) 即为所求。
差分代码如下:
for(int i=1;prime[i]<=maxx;i++)
for(int j=1;j*prime[i]<=maxx;j++)
F[j]-=F[j*prime[i]];