洛谷 - SP3871 GCDEX - GCD Extreme - 莫比乌斯反演
易得 $\sum\limits_{g=1}^{n} g \sum\limits_{k=1}^{n} \mu(k) \lfloor\frac{n}{gk}\rfloor  \lfloor\frac{n}{gk}\rfloor $
记 \(T=gk\) 枚举 \(T\) ,注意这里既然满足 \(T=gk\) 要保证两个乘起来确实是 \(T\) ,选择把 \(k\) 换成 $\frac{T}{g} $ .
$\sum\limits_{T=1}^{n} \lfloor\frac{n}{T}\rfloor \lfloor\frac{n}{T}\rfloor \sum\limits_{g|T} g\mu(\frac{T}{g}) $
$\sum\limits_{T=1}^{n} \lfloor\frac{n}{T}\rfloor \lfloor\frac{n}{T}\rfloor \varphi(T) $
猜了一下每次回答都是根号,可能可以,但是交上去T了。原来这个时限是200ms,太惊人了,这道题卡掉了所有其他的思路。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1000000;
int prime[MAXN+1];
int &ptop=prime[0];
ll Phi[MAXN+1];
inline void sieve(){
    const int &n=MAXN;
    Phi[1]=1;
    for(int i=2;i<=n;i++){
        if(!Phi[i]){
            ptop++;
            prime[ptop]=i;
            Phi[i]=i-1;
        }
        for(int j=1;j<=ptop;j++){
            int &p=prime[j];
            if(i*p>n)
                break;
            if(i%p){
                Phi[i*p]=Phi[i]*Phi[p];
            }
            else{
                Phi[i*p]=Phi[i]*p;
                break;
            }
        }
    }
    for(int i=1;i<=n;i++){
        Phi[i]+=Phi[i-1];
    }
}
inline ll H(int n){
    ll res=0;
    for(int l=1,r;l<=n;l=r+1){
        int t=n/l;
        r=n/t;
        res+=1ll*t*t*(Phi[r]-Phi[l-1]);
    }
    return res;
}
inline ll G(int n){
    ll res=(H(n)-1ll*n*(n+1)/2)/2;
    return res;
}
int main() {
#ifdef Yinku
    freopen("Yinku.in","r",stdin);
#endif // Yinku
    sieve();
    int n;
    while(~scanf("%d",&n)){
        if(n==0)
            break;
        else{
            printf("%lld\n",G(n));
        }
    }
}
问题在哪里?莫比乌斯反演不擅长进行多次回答,观察题目的数据可能想让我们用埃筛?
回到上面的式子。
其实因为是 \(n==m\) ,上面的反演很多余,枚举 \(g\) 的时候可以发现另一个公式,但是好像复杂度也是一样的,先留着,这个也是可以用杜教筛跑出大数据,应该比反演要快(因为这样大的Phi是比上面的少的)。
易得 $\sum\limits_{g=1}^{n} g \sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor} 2\varphi(i) - 1 $
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1000000;
int prime[MAXN+1];
int &ptop=prime[0];
ll Phi[MAXN+1];
inline void sieve(){
    const int &n=MAXN;
    Phi[1]=1;
    for(int i=2;i<=n;i++){
        if(!Phi[i]){
            ptop++;
            prime[ptop]=i;
            Phi[i]=i-1;
        }
        for(int j=1;j<=ptop;j++){
            int &p=prime[j];
            if(i*p>n)
                break;
            if(i%p){
                Phi[i*p]=Phi[i]*Phi[p];
            }
            else{
                Phi[i*p]=Phi[i]*p;
                break;
            }
        }
    }
    for(int i=1;i<=n;i++){
        Phi[i]+=Phi[i-1];
    }
}
inline ll s1(ll l,ll r){
    return (l+r)*(r-l+1)/2;
}
inline ll H(int n){
    ll res=0;
    for(int l=1,r;l<=n;l=r+1){
        int t=n/l;
        r=n/t;
        res+=(2ll*Phi[t]-1)*s1(l,r);
    }
    return res;
}
inline ll G(int n){
    ll res=(H(n)-1ll*n*(n+1)/2)/2;
    return res;
}
int main() {
#ifdef Yinku
    freopen("Yinku.in","r",stdin);
#endif // Yinku
    sieve();
    int n;
    while(~scanf("%d",&n)){
        if(n==0)
            break;
        else{
            printf("%lld\n",G(n));
        }
    }
}
一切从头开始,我们学习反演还有这些东西的初衷是想要降低单次回答的复杂度,看到原来的问题:
$ G(n) = \sum\limits_{i=1}{n-1}\sum\limits_{j=i+1}{n} gcd(i,j) \(
交换求和,这个没问题:
\) G(n) = \sum\limits_{j=2}{n}\sum\limits_{i=1}{j-1} gcd(i,j) $
记 $ H(n) = \sum\limits_{i=1}^{n-1} gcd(i,n) $
原式 \(G(n) = \sum\limits_{j=2}^{n} H(j)\)
貌似 \(H(n)\) 好像似曾相识? $ H(n) = ( \sum\limits_{i=1}^{n} gcd(i,n) ) - n$
里面这个不是前几天处理过?这种 \(gcd\) 就只可能是 \(n\) 的因子:
$ H(n) = ( \sum\limits_{d|n} d \sum\limits_{i=1}^{n} [gcd(i,n)d] ) - n$
$ H(n) = ( \sum\limits_{d|n} d \sum\limits_{i=1}^{\frac{n}{d}} [gcd(i,\frac{n}{d})1] ) - n$
$ H(n) = ( \sum\limits_{d|n} d \varphi(\frac{n}{d}) ) - n$
为方便,记 $ h(n) = \sum\limits_{d|n} d \varphi(\frac{n}{d}) $
意思是这个 \(h(n)\) 可以用埃筛,那么这个问题到这里就解决了,但是会不会有线筛的做法呢?
这个 \(id*\varphi\) 狄利克雷卷积在这里处理过。
那么来一波线性的做法:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1000000;
int prime[MAXN+1];
int &ptop=prime[0];
ll h[MAXN+1];
int pk[MAXN+1];
inline void sieve(){
    const int &n=MAXN;
    for(int i=2;i<=n;i++){
        if(!pk[i]){
            ptop++;
            prime[ptop]=i;
            pk[i]=i;
            h[i]=i+i-1;
        }
        for(int j=1;j<=ptop;j++){
            int &p=prime[j];
            int t=i*p;
            if(t>n)
                break;
            if(i%p){
                pk[t]=pk[p];
                h[t]=h[i]*h[p];
            }
            else{
                pk[t]=pk[i]*p;
                if(pk[t]==t){
                    h[t]=(t-i)+h[i]*p;
                }else{
                    h[t]=h[pk[t]]*h[t/pk[t]];
                }
                break;
            }
        }
    }
    for(int i=1;i<=n;i++){
        h[i]-=i;
    }
    for(int i=1;i<=n;i++){
        h[i]+=h[i-1];
    }
}
inline ll G(int n){
    ll res=h[n]-h[1];
    return res;
}
int main() {
#ifdef Yinku
    freopen("Yinku.in","r",stdin);
#endif // Yinku
    sieve();
    int n;
    while(~scanf("%d",&n)){
        if(n==0)
            break;
        else{
            printf("%lld\n",G(n));
        }
    }
}
洛谷 - SP3871 GCDEX - GCD Extreme - 莫比乌斯反演的更多相关文章
- 洛谷 P5518 - [MtOI2019]幽灵乐团 / 莫比乌斯反演基础练习题(莫比乌斯反演+整除分块)
		洛谷题面传送门 一道究极恶心的毒瘤六合一题,式子推了我满满两面 A4 纸-- 首先我们可以将式子拆成: \[ans=\prod\limits_{i=1}^A\prod\limits_{j=1}^B\p ... 
- [洛谷P1390]公约数的和·莫比乌斯反演
		公约数的和 传送门 分析 这道题很显然答案为 \[Ans=\sum_{i=1}^n\sum_{j=i+1}^n (i,j)\] //其中\((i,j)\)意味\(gcd(i,j)\) 这样做起来很烦, ... 
- 洛谷 - P4449 - 于神之怒加强版 - 莫比乌斯反演
		https://www.luogu.org/problemnew/show/P4449 \(F(n)=\sum\limits_{i=1}^{n}\sum\limits_{i=1}^{m} gcd(i, ... 
- 洛谷P2522 [HAOI2011]Problem b(莫比乌斯反演)
		题目描述 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. 输入输出格式 输入格式: 第一行一个整数 ... 
- 洛谷P3455 [POI2007]ZAP-Queries (莫比乌斯反演)
		题意:求$\sum_{i=1}^{a}\sum_{j=1}^{b}[gcd(i,j)==d]$(1<=a,b,d<=50000). 很套路的莫比乌斯反演. $\sum_{i=1}^{n}\ ... 
- 洛谷P3768 简单的数学题 莫比乌斯反演+杜教筛
		题意简述 求出这个式子 \[ \sum_{i=1}^n\sum_{j=1}^n ij(i,j) \bmod p \] 做法 先用莫比乌斯反演拆一下式子 \[ \begin{split} \sum_{i ... 
- 洛谷P3455 [POI2007]ZAP-Queries(莫比乌斯反演)
		传送门 设$$f(k)=\sum_{i=1}^{a}\sum_{j=1}^{b}[gcd(i,j)=k]$$ $$g(n)=\sum_{n|k}f(k)=\lfloor\frac{a}{n}\rflo ... 
- 洛谷 - P1390 - 公约数的和 - 莫比乌斯反演 - 欧拉函数
		https://www.luogu.org/problemnew/show/P1390 求 $\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m} gcd(i,j) $ ... 
- 洛谷P3312 [SDOI2014]数表(莫比乌斯反演+树状数组)
		传送门 不考虑$a$的影响 设$f(i)$为$i$的约数和 $$ans=\sum\limits_{i=1}^n\sum\limits_{j=1}^nf(gcd(i,j))$$ $$=\sum\limi ... 
随机推荐
- ZOJ 1516 Uncle Tom's Inherited Land(二分匹配 最大匹配 匈牙利啊)
			题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=516 Your old uncle Tom inherited a p ... 
- Swift高阶函数介绍(闭包、Map、Filter、Reduce)
			Swift语言有非常多函数式编程的特性.常见的map,reduce,filter都有,初看和python几乎相同,以下简介下 闭包介绍: 闭包是自包括的功能代码块,能够在代码中使用或者用来作为參数传值 ... 
- JSP学习笔记(一)
			JSP是基于JAVA语言的,区分大小写,HTML不区分大小写 如何建立Web服务目录? 1.在Webapps下面建立Web服务目录MYJSP 在Webapps下面新建文件夹MYJSP,将写好的jsp文 ... 
- Python学习笔记14:标准库之信号量(signal包)
			signal包负责在Python程序内部处理信号.典型的操作包含预设信号处理函数,暂停并等待信号,以及定时发出SIGALRM等. 要注意,signal包主要是针对UNIX平台(比方Linux, MAC ... 
- Mvc Autofac构造器注入
			新建MVC项目,添加程序集引用 定义接口ILog public interface ILog { string Save(string message); } 类TxtLog实现接口ILog publ ... 
- redis的主从复制和哨兵支持的主从切换
			1 主从复制的目的是为了读写分离 master写,然后同步到slave,slave只管读. 2 哨兵存在的目的 是为了主从切换,如果master挂了,那么一个slave成为master,重启之后的ma ... 
- 使用bat文件打开和关闭本地exe
			打开: cd 路径start AA.exe 关闭: taskkill /f /im AA.exe 
- LwIP移植uCos+stm32f407
			LwIP同操作系统一起工作的时候模型如下: 1.TCP/IP协议栈和应用程序以分离的任务运行 2.应用同协议栈沟通是通过API函数调用(API函数调用事实上就是通过OS自带的进程间通信机制,由应用程序 ... 
- vue项目刷新当前页面
			场景: 有时候我们在vue项目页面做了一些操作,需要刷新一下页面. 解决的办法及遇到的问题: this.$router.go(0).这种方法虽然代码很少,只有一行,但是体验很差.页面会一瞬间的白屏,体 ... 
- 使用adb命令查看android中的数据库
			在采用数据库操作时,经常会出现查询或删除等操作语句执行失败,但是有找不到具体原因.下面将介绍一种命令行方式进行数据库操作,来验证android中的数据库操作语句是否正确等. 具体操作步骤如下: (1) ... 
