51Nod1222 最小公倍数计数 数论 Min_25 筛
原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1222.html
题意
给定 $a,b$, 求
$$\sum_{n=a}^b \sum_{i=1}^n \sum_{j=1}^i [{\rm lcm } (i,j) = n]$$
$$a,b\leq 10^{11}$$
$${\rm Time \ Limit } = 6s$$
题解
本题做法很多。
Min_25 筛
先差分一下,转化成求前缀和。
先把原题的统计无序数对转化成统计有序数对,最终 $ans' = (ans+n)/2$ 即可。
设集合 $P$ 表示素数集合。
设 $c(n,p)$ 表示最大的使得 $p^{c(n,p)}|n$ 的数。
若 ${\rm lcm } (i,j) = n$ ,则
$$\forall p \in P, c(n,p)=\max(c(i,p),c(j,p))$$
所以,$\forall p\in P$ ,$c(i,p)$ 和 $c(j,p)$ 共有 $2c(n,p) +1 $ 种取值方法。
所以,设
$$n=\prod_i p_i^{k_i} (p_i\in P)$$
则
$$ \sum_{i=1}^n \sum_{j=1}^i [{\rm lcm } (i,j) = n] = \prod_t (2k_t+1) $$
显然这个式子满足 Min_25 筛的条件,直接筛就好了。
整除分块
$$S(n) = \sum_{i=1}^{n} \sigma_0(i^2)\\=\sum_{i=1}^n \sum_{d|i} 2^{\omega(d)}\\=\sum_{d=1}^n\lfloor \frac nd \rfloor 2^{\omega(d)}$$
整除分块一下,考虑
$$\sum_{i=1}^n 2^{\omega (i)} = \sum_{i=1}^n \sum_{d|i} \mu(d)^2\\=\sum_{d=1}^n\lfloor \frac nd \rfloor \mu(d) ^2$$
再整除分块,再推
$$\sum_{i=1}^n \mu (i)^2 = \sum_{i=1}^n \mu(i) \lfloor \frac n {i^2} \rfloor$$
于是只要求个 $\mu$ 的前缀和。
看起来要杜教筛,但是……
由于这里 $i^2\leq n$,所以只需要暴力预处理前缀和就好了。
注意这个做法可能会被卡常数!
复杂度正确的暴力
$$S(k) = \sum_{n=1}^k\sum_{i=1}^{n}\sum_{j=1}^n [{\rm lcm}(i,j) = n]$$
$$=\sum_{n=1}^k\sum_{d=1}^n\sum_{i=1}^n\sum_{j=1}^n[ijd=n] [\gcd(i,j) = 1]$$
$$=\sum_{p=1}^k\mu(p) \sum_{i,j,d} [ijd\leq \frac{k} {p^2}]$$
先枚举个 $p$ ,再强制 $i,j,d$ 单调不降,枚举 $i$ 再枚举 $j$ ,暴力计算。
证明一下时间复杂度:
$$T(n) = O\left(\sum_{p=1}^{\sqrt n} \sum_{i=1}^{\sqrt[3]{\frac{n}{p^2}}} \sqrt{\left\lfloor \frac{n}{p^2i}\right\rfloor}\right) $$
$$\because O\left(\sum_{i=1}^{\sqrt[3]{n}}\sqrt{ \frac n i}\right) = O\left(\int _{1}^{\sqrt[3]{n}} \sqrt{\frac n x} {\rm d} x\right)\\=O\left(\sqrt{n}\int _{1}^{\sqrt[3]{n}} x^{-0.5} {\rm d} x\right)=O\left(\sqrt{n}\cdot 0.5 \left(\sqrt[3]{n}\right) ^{0.5}\right)=O\left(n^{\frac 2 3 }\right)$$
$$\therefore T(n) = O\left(\sum_{p=1}^{\sqrt n} \sum_{i=1}^{\sqrt[3]{\frac{n}{p^2}}} \sqrt{\lfloor \frac{n}{p^2i}\rfloor}\right)=O\left(\sum_{p=1}^{\sqrt{n}} \left(\frac n {p^2} \right) ^{\frac 2 3 } \right)=O\left(n^{\frac 2 3}\int _1^\sqrt n x^{-\frac 4 3} {\rm d} x \right) \\=O\left( n^\frac 23 \cdot -1\cdot (\left (\sqrt n\right)^{-\frac 13} - 1)\right) = O\left(n^\frac 23 (1-n^{-\frac 16})\right) = O\left(n^\frac 23\right)$$
没想到这个“暴力”的复杂度居然是对的!代码短小精悍,吊打前几种做法了!
代码1 - Min_25 筛
#pragma GCC optimize("Ofast","inline")
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
using namespace std;
typedef long long LL;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int Base=1000005,N=Base*2+5;
LL n,cn,a,b,base;
LL h[N],ps[N],cnt;
LL p[N],pcnt;
#define ID(i) ((i)<=base?i:cnt-cn/(i)+1)
LL f(int e){
return e*2+1;
}
LL g(LL n,LL m){
LL ans=max(0LL,h[ID(n)]-h[ID(p[m-1])]);
for (int i=m;i<=pcnt&&p[i]*p[i]<=n;i++){
LL nn=n/p[i];
for (int e=1;nn>0;e++,nn/=p[i])
ans+=f(e)*((e>1)+g(nn,i+1));
}
return ans;
}
LL _solve(LL _n){
cn=n=_n,base=(LL)sqrt(n),cnt=pcnt=0;
for (LL i=1;i<=n;i=ps[cnt]+1)
ps[++cnt]=n/(n/i),h[cnt]=ps[cnt]-1;
p[0]=1;
for (LL i=2;i<=base;i++)
if (h[i]!=h[i-1]){
p[++pcnt]=i;
LL i2=i*i;
for (LL j=cnt;ps[j]>=i2;j--)
h[j]-=h[ID(ps[j]/i)]-(pcnt-1);
}
for (LL i=1;i<=cnt;i++)
h[i]*=3;
return g(n,1)+1;
}
LL solve(LL n){
return (_solve(n)+n)/2;
}
int main(){
a=read(),b=read();
cout<<solve(b)-solve(a-1)<<endl;
return 0;
}
代码2 - 整除分块
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
using namespace std;
typedef long long LL;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=11000005;
const LL nb=1e11,un=N-5;
int p[N/5],pcnt;
bool vis[N],_u2[N];
char u[N];
int u2[N],w[N];
unordered_map <LL,LL> U2,W;
LL A;
void get_prime(int n){
pcnt=0,u[1]=1;
for (register int i=2;i<=n;i++){
if (!vis[i])
p[++pcnt]=i,u[i]=-1,w[i]=1;
for (register int j=1;j<=pcnt&&p[j]*i<=n;j++){
vis[i*p[j]]=1;
if (i%p[j])
u[i*p[j]]=-u[i],w[i*p[j]]=w[i]+1;
else {
u[i*p[j]]=0,w[i*p[j]]=w[i];
break;
}
}
}
}
void prework(int n){
get_prime(n);
for (int i=1;i<=n;i++){
_u2[i]=u[i]*u[i];
// u[i]+=u[i-1];
u2[i]=u2[i-1]+_u2[i];
w[i]=1LL<<w[i];
w[i]+=w[i-1];
}
}
LL getU2(LL n){
if (n<=un)
return u2[n];
if (U2.count(n))
return U2[n];
LL ans=0;
ans=0;
for (LL i=1;i*i<=n;i++)
ans+=u[i]?u[i]*(n/(i*i)):0;
return U2[n]=ans;
}
LL getW(LL n){
if (n<=un)
return w[n];
if (W.count(n))
return W[n];
LL ans=0;
LL pr=0,nw,sq=(LL)sqrt(n);
for (LL i=1;i<=sq;i++)
ans+=_u2[i]?n/i:0;
pr=u2[sq];
for (LL i=sq+1,j;i<=n;i=j+1){
j=n/(n/i);
nw=j<=un?u2[j]:getU2(j);
ans+=(nw-pr)*(n/i);
pr=nw;
}
return W[n]=ans;
}
LL getS(LL n){
if (!n)
return 0;
LL ans=0,pr=0,nw;
for (LL i=1,j;i<=n;i=j+1){
j=n/(n/i);
nw=j<=un?w[j]:getW(j);
ans+=(nw-pr)*(n/i);
pr=nw;
}
return ans;
}
LL solve(LL n){
if (!n)
return 0;
A=n;
return (getS(n)+n)/2;
}
int main(){
prework(N-5);
LL a=read(),b=read();
cout<<solve(b)-solve(a-1)<<endl;
return 0;
}
代码3 - 优秀的暴力
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e5+10;
int mu[N],l,r;
int calc(int x){
int re=0;
for (int i=1;i*i<=x;i++)
if (mu[i]){
int tmp=0,m=x/(i*i);
for (int j=1;j*j*j<=m;j++){
tmp+=(m/(j*j)-j)*3+1;
for (int k=j+1;j*k*k<=m;k++)
tmp+=(m/(j*k)-k)*6+3;
}
re+=mu[i]*tmp;
}
return (re+x)/2;
}
signed main(){
mu[1]=1;
for (int i=1;i<N;i++)
for (int j=i+i;j<N;j+=i)
mu[j]-=mu[i];
scanf("%lld%lld",&l,&r);
printf("%lld",calc(r)-calc(l-1));
return 0;
}
51Nod1222 最小公倍数计数 数论 Min_25 筛的更多相关文章
- LOJ3069. 「2019 集训队互测 Day 1」整点计数(min_25筛)
题目链接 https://loj.ac/problem/3069 题解 复数真神奇. 一句话题意:令 \(f(x)\) 表示以原点 \((0, 0)\) 为圆心,半径为 \(x\) 的圆上的整点数量, ...
- 模板 - 数学 - 数论 - Min_25筛
终于知道发明者的正确的名字了,是Min_25,这个筛法速度为亚线性的\(O(\frac{n^{\frac{3}{4}}}{\log x})\),用于求解具有下面性质的积性函数的前缀和: 在 \(p\) ...
- 51nod1222 最小公倍数计数
题目来源: Project Euler 基准时间限制:6 秒 空间限制:131072 KB 分值: 640 定义F(n)表示最小公倍数为n的二元组的数量. 即:如果存在两个数(二元组)X,Y(X & ...
- 51nod1222最小公倍数计数
51nod1222 http://210.33.19.103/contest/1113/problem/2 同学的神仙做法: 首先考虑先去掉X<=Y的限制,也就是先计算满足要求的任意有序pair ...
- 51nod1222 最小公倍数计数 莫比乌斯反演 数学
求$\sum_{i = 1}^{n} \sum_{j = 1}^{i} [lcm(i, j) \le n]$因为这样不好求,我们改成求$\sum_{i = 1}^{n} \sum_{j = 1}^{n ...
- [51nod1222] 最小公倍数计数(莫比乌斯反演)
题面 传送门 题解 我此生可能注定要和反演过不去了--死都看不出来为啥它会突然繁衍反演起来啊-- 设\(f(n)=\sum_{i=1}^n\sum_{j=1}^n[{ij\over\gcd(i,j)} ...
- Min_25 筛 学习笔记
原文链接https://www.cnblogs.com/zhouzhendong/p/Min-25.html 前置技能 埃氏筛法 整除分块(这里有提到) 本文概要 1. 问题模型 2. Min_25 ...
- 【51nod】1222 最小公倍数计数 莫比乌斯反演+组合计数
[题意]给定a和b,求满足a<=lcm(x,y)<=b && x<y的数对(x,y)个数.a,b<=10^11. [算法]莫比乌斯反演+组合计数 [题解]★具体 ...
- 51NOD 1222 最小公倍数计数 [莫比乌斯反演 杜教筛]
1222 最小公倍数计数 题意:求有多少数对\((a,b):a<b\)满足\(lcm(a,b) \in [1, n]\) \(n \le 10^{11}\) 卡内存! 枚举\(gcd, \fra ...
随机推荐
- SpringMVC中使用Interceptor拦截器顺序
一.简介 SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理.比如通过它来进行权限验 证,或者是来判断用户是否登陆,或者是像1 ...
- webpack学习记录-初步体验(一)
一.关于webpack 自从出现模块化以后,大家可以将原本一坨代码分离到个个模块中,但是由此引发了一个问题.每个 JS 文件都需要从服务器去拿,由此会导致加载速度变慢.Webpack 最主要的目的就是 ...
- Codeforces 1077F2 Pictures with Kittens (hard version)(DP+单调队列优化)
题目链接:Pictures with Kittens (hard version) 题意:给定n长度的数字序列ai,求从中选出x个满足任意k长度区间都至少有一个被选到的最大和. 题解:数据量5000, ...
- 应用调试(四)系统调用SWI
目录 应用调试(四)系统调用SWI 系统调用 SWI代码片段分析 分析sys_write 构造sys_hello 应用程序调用SWI 嵌入汇编语法 测试APP 参考 title: 应用调试(四)系统调 ...
- MySQL_表锁_lock tables tableName read
pre.环境准备 1.建立两个表S,T,并插入一些数据 --创建表S create table S(d int) engine=innodb; ); --创建表T create table T(c i ...
- java.util.ConcurrentModificationException异常原因及解决方法
在java语言中,ArrayList是一个很常用的类,在编程中经常要对ArrayList进行删除操作,在使用remove方法对ArrayList进行删除操作时,报java.util.Concurren ...
- tolua之wrap文件的原理与使用
什么是wrap文件 每个wrap文件都是对一个c#类的包装,在lua中,通过对wrap类中的函数调用,间接的对c#实例进行操作. wrap类文件生成和使用的总体流程 生成一个wrap文件的流程 这部分 ...
- 第十三节:HttpHander扩展及应用(自定义扩展名、图片防盗链)
一. 自定义扩展名 1. 前言 凡是实现了IHttpHandler接口的类均为Handler类,HttpHandler是一个HTTP请求的真正处理中心,在HttpHandler容器中,ASP.NET ...
- [再寄小读者之数学篇](2014-06-22 求极限 [中国科学技术大学2011年高等数学B考研试题])
设数列 $\sed{x_n}$ 满足 $0<x_1<\pi$, $x_{n+1}=\sin x_n\ (n=1,2,\cdots)$. (1) 证明 $\dps{\vlm{n}x_n}$ ...
- 【搞事情】VS2015下的openGL初始化
环境:glfw+glew+visual studio 2015 原材料下载链接: glfw 下载 glew 下载 glm库 下载 cmake 下载 (我下载的时候有些官网戳不开(大概校园网问题)... ...