[51Nod 1584] 加权约数和

Description

在整理以前的试题时,他发现了这样一道题目:“求 \(\sum\sigma(i)\),其中 \(1≤i≤N\),\(σ(i)\) 表示 \(i\) 的约数之和。”

现在他长大了,题目也变难了,所以麻烦你来帮他解决一道数论题吧。

他需要你求如下表达式的值:

\[
\sum_{i=1}^N\sum_{j=1}^N\max(i,j)?σ(i?j)
\]
其中 \(\max(i,j)\) 表示 \(i\) 和 \(j\) 里的最大值,\(\sigma(i?j)\) 表示 \(i?j\) 的约数之和。

例如当 \(N=2\) 的时候,由 \(σ(1)=1,σ(2)=1+2=3,σ(4)=1+2+4=7\) 可知,答案应为 \(1?σ(1?1)+2?σ(1?2)+2?σ(2?1)+2?σ(2?2)=27\)。

他发现答案有点大,所以你只需要告诉他答案模 \(1000000007\) 的值即可。

Input

每个测试点含有多组测试数据。

第一行是一个正整数 \(T\),表示接下来有 \(T\) 组测试数据。

接下来的 \(T\) 行,每组测试数据占一行。

每行有一个正整数 \(N\),含义如描述所示。

Output

共有 \(T\) 行。对于每组测试数据,输出一行信息"Case #x: y"。

其中 \(x\) 表示对应的是第几组测试数据,\(y\) 表示相应的答案模 \(1000000007\) 的值。

Sample Input

5
1
2
3
4
5

Sample Output

Case #1: 1
Case #2: 27
Case #3: 162
Case #4: 686
Case #5: 1741

HINT

\(1≤T≤50000,1≤N≤1000000\)

Solution

〖一〗

\[
\sigma(i\cdot j)=\sum\limits_{p\mid i}\sum\limits_{q\mid j}[\left(p,q)=1\right]\dfrac{p\cdot j}{q}
\]

证明:原式 \(=\sum\limits_{p\mid i}\sum\limits_{q\mid j}\left[\left(p,\dfrac{j}{q}\right)=1\right]p\cdot q\),设 \(i=\sum p_i^{a_i},j=\sum p_i^{b_i},p=\sum p_i^{c_i},q=\sum p_i^{d_i}\)。

  • 若 \(0<c_i\le a_i\),则 \(d_i=b_i\),此时可以表示出 \(p_i^{(b_i+1)\rightarrow(b_i+a_i)}\);
  • 若 \(c_i=0\),则 \(0\le d_i\le b_i\),此时可以表示出 \(p_i^{0\rightarrow b_i}\)。

综上,该式一定可以表示出 \(p_i^{0\rightarrow(b_i+a_i)}\)。

〖二〗

\[
\sum_{i=1}^n\sum_{j=1}^n\max(i,j)?σ(i?j)=2\sum_{i=1}^{n}\sum_{j=1}^{i}i\cdot\sigma(i\cdot j)-\sum_{i=1}^ni\cdot\sigma(i^2)
\]

\[
\begin{eqnarray}
\sum_{i=1}^ni\cdot\sigma(i^2)&=&\sum_{i=1}^{n}i\sum_{p\mid i}\sum_{q\mid i}[(p,q)=1]\frac{p\cdot i}{q}\&=&\sum_{d=1}^{n}\mu(d)\sum_{i=1}^{n}i\sum_{p\mid i}\sum_{q\mid i}[d\mid(p,q)]\frac{p\cdot i}{q}\&=&\sum_{d=1}^{n}\mu(d)\sum_{i=1}^{n}i\sum_{d\mid p\mid i}\sum_{d\mid q\mid i}\frac{p\cdot i}{q}\&=&\sum_{d=1}^{n}\mu(d)\cdot d^2\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}i\sum_{p\mid i}p\sum_{q\mid i}\frac{i}{q}\&=&\sum_{d=1}^{n}\mu(d)\cdot d^2\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}i\left(\sum_{p\mid i}p\right)^2
\end{eqnarray}
\]

\[
\begin{eqnarray}
\sum_{i=1}^{n}\sum_{j=1}^{i}i\cdot \sigma(i\cdot j)&=&\sum_{i=1}^{n}\sum_{j=1}^{i}i\sum_{p\mid i}\sum_{q\mid j}[(p,q)=1]\frac{p\cdot j}{q}\&=&\sum_{d=1}^{n}\mu(d)\sum_{i=1}^{n}\sum_{j=1}^{i}i\sum_{p\mid i}\sum_{q\mid j}[d\mid(p,q)]\frac{p\cdot j}{q}\&=&\sum_{d=1}^{n}\mu(d)\cdot d^2\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}i\sum_{p\mid i}p\sum_{j=1}^{i}\sum_{q\mid j}\frac{j}{q}\&=&\sum_{d=1}^{n}\mu(d)\cdot d^2\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}i\sum_{p\mid i}p\sum_{j=1}^{i}\sum_{q\mid j}q
\end{eqnarray}
\]

而这样只能做到 \(O(\sqrt n)\) 询问,于是进一步化简:

\[
\begin{eqnarray}
\sum_{d=1}^{n}\mu(d)\cdot d^2\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}f(i)&=&\sum_{i=1}^n\sum_{d\mid i}\mu(d)\cdot d^2\cdot f\left(\frac{i}{d}\right)
\end{eqnarray}
\]

第一个式子中的 \(d\) 是 \(i\cdot d\) 的约数,第二个式子中的 \(i\) 表示 \(i\cdot d\),\(d\) 还是约数,因此两个式子相等。

然后就可以 \(O(n\ln n)\) 预处理,\(O(1)\) 查询了。

Code

#include <cstdio>

const int N = 1000005, mod = 1000000007;
int mu[N], np[N], p[N], tot, a[N], b[N], f[N], g[N], n = 1000000;

int read() {
    int x = 0; char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    return x;
}
void euler() {
    mu[1] = 1;
    for (int i = 2; i <= n; ++i) {
        if (!np[i]) p[++tot] = i, mu[i] = -1;
        for (int j = 1; j <= tot && i * p[j] <= n; ++j) {
            np[i * p[j]] = 1;
            if (i % p[j] == 0) { mu[i * p[j]] = 0; break; }
            mu[i * p[j]] = -mu[i];
        }
    }
}
int main() {
    euler();
    for (int i = 1; i <= n; ++i)
        for (int j = i; j <= n; j += i)
            if ((a[j] += i) >= mod) a[j] -= mod;
    for (int i = 1; i <= n; ++i) if ((b[i] = b[i - 1] + a[i]) >= mod) b[i] -= mod;
    for (int i = 1; i <= n; ++i)
        for (int j = i; j <= n; j += i) {
            f[j] = (f[j] + 1LL * mu[i] * i * j % mod * a[j / i] % mod * b[j / i]) % mod;
            g[j] = (g[j] + 1LL * mu[i] * i * j % mod * a[j / i] % mod * a[j / i]) % mod;
        }
    for (int i = 2; i <= n; ++i) {
        if ((f[i] += f[i - 1]) >= mod) f[i] -= mod;
        if (f[i] < 0) f[i] += mod; //mu可能是负数, 需要判断正负
        if ((g[i] += g[i - 1]) >= mod) g[i] -= mod;
        if (g[i] < 0) g[i] += mod;
    }
    int T = read();
    for (int i = 1; i <= T; ++i) n = read(), printf("Case #%d: %lld\n", i, (2LL * f[n] + mod - g[n]) % mod);
    return 0;
}

原文地址:https://www.cnblogs.com/fly-in-milkyway/p/10373151.html

时间: 2024-10-25 07:35:06

[51Nod 1584] 加权约数和的相关文章

51nod1584加权约数和

题目大意: 求: \[ \sum_{i-1}^n\sum_{j=1}^nmax(i,j)\sigma(i*j) \] 题解 对于这个\(\max\),套路的把它转化成: \[ 2*\sum_{i=1}^n\sum_{j=1}^ii*\sigma(i*j)-\sum_{i=1}^n i*\sigma(i*i) \] 对于前面的部分,我们可以: \[ \sum_{i=1}^{n}\sum_{j=1}^ii\sum_{a|i}\sum_{b|j}a*\frac{j}{b}[(a,b)==1] \] \

浅谈一类积性函数的前缀和(转载)

本文转自:http://blog.csdn.net/skywalkert/article/details/50500009 另外,莫比乌斯反演和杜教筛其他可转到 http://blog.leanote.com/post/totziens/%E8%8E%AB%E6%AF%94%E4%B9%8C%E6%96%AF%E5%8F%8D%E6%BC%94 写在前面 笔者在刷题过程中遇到一些求积性函数前缀和的问题,其中有一类问题需要在低于线性时间复杂度的算法,今天就来浅析一下这类问题的求解方法,当作以后讲课

杜教筛 学习总结

看了看唐老师的blog,照猫画虎的做了几道题目,感觉对杜教筛有些感觉了 但是稍微有一点难度的题目还是做不出来,放假的时候争取都A掉(挖坑ing) 这篇文章以后等我A掉那些题目之后再UPD上去就好啦 由于懒得去写怎么用编辑器写公式,所以公式就准备直接copy唐老师的啦 首先积性函数和完全积性函数什么的就不再多说了 列举常见的积性函数: 1.约数个数函数和约数个数和函数 2.欧拉函数phi 3.莫比乌斯函数mu 4.元函数e 其中e(n)=[n==1] 5.恒等函数I 其中I(n)=1 6.单位函数

【算法总结】积性函数相关

[线性筛] [模板代码] [线性筛质数] 1 int main() 2 { 3 n=read(); 4 for(int i=2;i<=n;i++) 5 { 6 if(!f[i])pri[++cnt]=i; 7 for(int j=1;j<=cnt;j++) 8 { 9 if(i*pri[j]>n)break; 10 f[i*pri[j]]=1; 11 if(i%pri[j]==0)break; 12 } 13 } 14 } [线性求约数和] 1 void pre() 2 { 3 miu[

51nod 1220 约数之和(杜教筛 + 推推推推推公式)

题意 给出\(n(1\leq n \leq 10^9)\),求\(\sum_{i=1}^n\sum_{j=1}^n\sigma(ij)\),其中\(\sigma(n)\)表示\(n\)的约数之和. balabala 交了两道杜教筛的的板子题(51nod 1239, 1244)就看到了这题,然后不会搞,然后看题解看了一天一夜终于彻底搞明白一发A掉了...感觉学到了很多,写个博客整理一下,如有错请指出. 技能需求 数论函数与线性筛 莫比乌斯反演(也可以当成容斥去理解) 狄利克雷卷积 杜教筛 强大的数

51nod 约数和(数论)

题目链接: 约数和 基准时间限制:2 秒 空间限制:131072 KB 分值: 80 有三个下标从1到n的数组a.b.c. a数组初始全为0. b[i]=∑j|ia[j] c[i]=∑j|ib[j] 需要进行下列操作: 1 x y :将a[x]加上y 2 x :询问当前c[x]的值 j | i 表示j是i的约数. Input 第一行两个整数,n和q,分别表示数组下标范围和操作次数.(1<=n,q<=1,000,000) 接下来q行,描述一个操作.(x随机,1<=x<=n,1<

51nod - 1586 - 约数和 - 水题

https://www.51nod.com/Challenge/Problem.html#problemId=1586 一眼看过去居然一点思路都没有的,一言不合就打表,打贡献表. #include <bits/stdc++.h> using namespace std; typedef long long ll; int n = 25; int a[200]; void update_b(int id) { for(int i = 1; i <= id; ++i) { if(id % i

51nod 1220 约数之和

约数之和 Problem d(k)表示k的所有约数的和.d(6) = 1 + 2 + 3 + 6 = 12. 定义S(N) = ∑1<=i<=N ∑1<=j<=N d(i*j). 例如:S(3) = d(1) + d(2) + d(3) + d(2) + d(4) + d(6) + d(3) + d(6) + d(9) = 59,S(1000) = 563576517282. 给出正整数N,求S(N),由于结果可能会很大,输出Mod 1000000007(10^9 + 7)的结果.

51Nod 1419 最小公倍数挑战

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1419 题意: 思路: 要想最大,肯定去找尽量大的互质的数,如果不是互质的数,去掉约数后也就变成了互质数. 相邻的数肯定是互质的,如果n是奇数,那么n和n-1也是互质的,此时n*(n-1)*(n-2)就是最大值. 如果是偶数的话,就得去考虑n和n-3是否互质,如果互质,则最大值就是n*(n-1)*(n-3),否则就是(n-1)*(n-2)*(n-3). 1 #includ