题目链接:哆啦A梦传送门
题意:
求 f ( n ) = ∑ i = 1 n ∑ j = 1 i ⌈ n i ⌉ [ g c d ( i , j ) = = 1 ] f(n)=\sum_{i=1}^{n}\sum_{j=1}^{i}\lceil \frac{n}{i} \rceil [gcd(i,j)==1] f(n)=∑i=1n∑j=1i⌈in⌉[gcd(i,j)==1]
题解:参考博客:神犇
此公式大部分都是参考博客里面的。写这篇只是为了自己以后好复习回顾。
我们先化简一下:
f ( n ) = ∑ i = 1 n ∑ j = 1 i ⌈ n i ⌉ [ g c d ( i , j ) = = 1 ] = ∑ i = 1 n ( ∑ j = 1 i ⌊ n i ⌋ [ g c d ( i , j ) = = 1 ] + ϕ ( n ) − 1 ) 只 有 n 与 i 互 质 时 , 向 上 取 整 才 会 多 1 = ∑ i = 1 n ∑ j = 1 i ( ⌊ n i ⌋ [ g c d ( i , j ) = = 1 ] ) + ∑ i = 1 n ϕ ( n ) − n \begin{aligned} f(n)&=\sum_{i=1}^{n}\sum_{j=1}^{i}\lceil \frac{n}{i} \rceil [gcd(i,j)==1]\\ &=\sum_{i=1}^{n}(\sum_{j=1}^{i}\lfloor \frac{n}{i} \rfloor [gcd(i,j)==1]+\phi(n)-1) 只有n与i互质时,向上取整才会多1\\ &=\sum_{i=1}^{n}\sum_{j=1}^{i}(\lfloor \frac{n}{i} \rfloor [gcd(i,j)==1])+\sum_{i=1}^{n}\phi(n)-n\\ \end{aligned} f(n)=i=1∑nj=1∑i⌈in⌉[gcd(i,j)==1]=i=1∑n(j=1∑i⌊in⌋[gcd(i,j)==1]+ϕ(n)−1)只有n与i互质时,向上取整才会多1=i=1∑nj=1∑i(⌊in⌋[gcd(i,j)==1])+i=1∑nϕ(n)−n
我们再设:
首先我们要知道莫比乌斯函数有这样一个性质: ∑ d ∣ n u ( d ) = [ n = = 1 ] \sum_{d|n}u(d) =[n==1] ∑d∣nu(d)=[n==1]
g ( n ) = ∑ i = 1 n ∑ j = 1 i ( ⌊ n i ⌋ [ g c d ( i , j ) = = 1 ] ) = ∑ i = 1 n ∑ j = 1 i ( ⌊ n i ⌋ ∑ d ∣ ( i , j ) u ( d ) ) 我 们 现 在 枚 举 d , 设 i = k 1 d , j = k 2 d , 那 么 有 = ∑ d = 1 n u ( d ) ∑ k 1 n / d ∑ k 2 k 1 ⌊ k 1 k 2 ⌋ \begin{aligned}g(n)&=\sum_{i=1}^{n}\sum_{j=1}^{i}(\lfloor \frac{n}{i} \rfloor [gcd(i,j)==1])\\ &=\sum_{i=1}^{n}\sum_{j=1}^{i}(\lfloor \frac{n}{i} \rfloor \sum_{d|(i,j)}u(d))\\ 我们现在枚举d,设i=k_1d,j=k_2d,那么有\\ &=\sum_{d=1}^{n}u(d)\sum_{k_1}^{n/d}\sum_{k_2}^{k_1}\lfloor \frac{k_1}{k_2}\rfloor \\ \end{aligned} g(n)我们现在枚举d,设i=k1d,j=k2d,那么有=i=1∑nj=1∑i(⌊in⌋[gcd(i,j)==1])=i=1∑nj=1∑i(⌊in⌋d∣(i,j)∑u(d))=d=1∑nu(d)k1∑n/dk2∑k1⌊k2k1⌋
我们知道: ∑ i = 1 n ⌊ n i ⌋ = ∑ i = 1 n σ ( i ) , σ ( i ) 表 示 i 的 正 因 子 个 数 。 \begin{aligned}\sum_{i=1}^{n}\lfloor \frac{n}{i}\rfloor=\sum_{i=1}^{n} \sigma(i) , \sigma(i)表示i的正因子个数。\end{aligned} i=1∑n⌊in⌋=i=1∑nσ(i),σ(i)表示i的正因子个数。
一 个 很 简 单 的 证 明 , 对 于 每 个 i , ⌊ n i ⌋ 表 示 在 [ 1 , n ] 中 有 ⌊ n i ⌋ 个 因 子 i 例 如 : i 等 于 1 , n = 4 , ⌊ 4 1 ⌋ = 4 , 即 在 [ 1 , 4 ] 中 每 个 数 都 存 在 因 子 1 \begin{aligned} 一个很简单的证明,对于每个i,\lfloor \frac{n}{i}\rfloor表示在[1,n]中有\lfloor \frac{n}{i}\rfloor个因子i\\ 例如:i等于1,n=4, \lfloor \frac{4}{1}\rfloor=4,即在[1,4]中每个数都存在因子1\end{aligned} 一个很简单的证明,对于每个i,⌊in⌋表示在[1,n]中有⌊in⌋个因子i例如:i等于1,n=4,⌊14⌋=4,即在[1,4]中每个数都存在因子1
那么上式就可化简为:
g ( n ) = ∑ d = 1 n u ( d ) ∑ k 1 n / d ∑ k 2 k 1 ⌊ k 1 k 2 ⌋ = ∑ d = 1 n u ( d ) ∑ k 1 n / d ∑ k 2 k 1 σ ( k 2 ) \begin{aligned}g(n)&=\sum_{d=1}^{n}u(d)\sum_{k_1}^{n/d}\sum_{k_2}^{k_1}\lfloor \frac{k_1}{k_2}\rfloor \\ &=\sum_{d=1}^{n}u(d)\sum_{k_1}^{n/d}\sum_{k_2}^{k_1} \sigma(k_2)\\\end{aligned} g(n)=d=1∑nu(d)k1∑n/dk2∑k1⌊k2k1⌋=d=1∑nu(d)k1∑n/dk2∑k1σ(k2)
我们设 h ( n ) = ∑ i n ∑ j i σ ( j ) \begin{aligned}h(n)=\sum_{i}^{n}\sum_{j}^{i} \sigma(j)\end{aligned} h(n)=i∑nj∑iσ(j),这个我们可以先线性筛出来 σ ( n ) \sigma(n) σ(n),接着预处理前缀和就可以求得 h ( n ) h(n) h(n)。
那么最终的式子就为:
f ( n ) = ∑ d = 1 n u ( d ) h ( n d ) + ∑ i = 1 n ϕ ( n ) − n \begin{aligned}f(n)=\sum_{d=1}^{n}u(d)h(\frac{n}{d})+\sum_{i=1}^{n}\phi(n)-n\end{aligned} f(n)=d=1∑nu(d)h(dn)+i=1∑nϕ(n)−n
我们现在总结下:
根据题目给的公式或者自己推的公式:
1,如果有向上取整的,先化成向下取整(一般跟欧拉函数挂钩)。
2,看到有某个 [条件变量=1],我们此时要能反应出莫比乌斯反演的一个性质: ∑ d ∣ 条 件 变 量 u ( d ) \sum_{d|条件变量}u(d) ∑d∣条件变量u(d) ,接着我们就把d给拿出来枚举,并让其它积分变量满足相应的条件(一般n/d等等)
3,接着我们要熟记一些公式,因为我们可以将它们替换,例如此题的 ∑ i = 1 n ⌊ n i ⌋ = ∑ i = 1 n σ ( i ) , σ ( i ) 表 示 i 的 正 因 子 个 数 。 \begin{aligned}\sum_{i=1}^{n}\lfloor \frac{n}{i}\rfloor=\sum_{i=1}^{n} \sigma(i) , \sigma(i)表示i的正因子个数。\end{aligned} i=1∑n⌊in⌋=i=1∑nσ(i),σ(i)表示i的正因子个数。公式。
4,有些化简后的式子不是我们常用的能被替换的公式(此公式很容易求得),那么此时就很可能要想到这是不是积性函数,要是的话,我们就要往这方面去做了,但有时积性函数不好判断,也可以大胆假设它就为积性函数,因为大部分我们遇到的都是积性函数。不过我们还是得到掌握下积性函数的判别方法,比如,我们要积累一些积性函数,多个积性函数相乘也为积性函数。知道是积性函数之后,我们就可以在线性筛那里把它们给筛出来。
线性筛分为3部分:
1.n本身是素数,这个根据积性函数的定义可得,很容易求。
2.i%prime[j]!=0,这个也是根据积性函数的性质可得,即f(a)f(b)=f(ab)。
3.i%prime[j]==0,这个可能需要找规律加灵光一闪。
代码:
#include
using namespace std;
const int N=1e6+10;
typedef long long LL;
const LL mod=1e9+7;
int prime[N],tot;/// 筛素数 ,从0下标开始存储
int mu[N];///莫比乌斯函数
int phi[N]; ///欧拉函数
///facnum[i]表示i的约数个数,d[i],表示i的最小质因子的次幂
int facnum[N],d[N];
bool vis[N];
///函数h,欧拉函数前缀和,莫比乌斯前缀和
LL h[N],sum_phi[N],sum_mu[N];
void init()
{
tot = 0;
phi[1] = 1;
mu[1] = 1;
facnum[1] = 1;
for(int i = 2; i < N; i++)
{
if(!vis[i])
{
phi[i] = i - 1;
mu[i] = -1;
prime[tot++] = i;
facnum[i] = 2;
d[i] = 1;
}
for(int j = 0; j < tot && i * prime[j] < N; j++)
{
vis[i * prime[j]] = true;
if(i % prime[j] == 0)
{
phi[i * prime[j]] = phi[i] * prime[j];
mu[i * prime[j]] = 0;
facnum[i * prime[j]] = facnum[i] / (d[i] + 1) * (d[i] + 2);
d[i * prime[j]] = d[i] + 1;
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
mu[i * prime[j]] = -mu[i];
facnum[i * prime[j]] = facnum[i] * 2;
d[i * prime[j]] = 1;
}
}
sum_phi[0]=0;
LL item=0;
for(int i=1;i