51NOD 1222 最小公倍数计数 [莫比乌斯反演 杜教筛]
1222 最小公倍数计数
题意:求有多少数对\((a,b):a<b\)满足\(lcm(a,b) \in [1, n]\)
\(n \le 10^{11}\)
卡内存!
枚举\(gcd, \frac{a}{gcd}, \frac{b}{gcd}\),然后\(\mu\)代入,就是
\]
问题就是怎么求后面的式子了
一开始我是
g(n) = \sum_{i=1}^n \sigma(i)
\]
杜教筛\(g\),方法是卷上\(\mu\),当然还要杜教筛\(\sum\mu\),但不影响复杂度,还是\(O(n^{\frac{2}{3}})\)
本机6.5s,改小预处理的大小后当然T了
然后又用分块的方法算\(g\),预处理前\(O(n^{2/3})\)的\(\sigma\)剩下的分块\(O({\sqrt{n}})\)计算,复杂度也是\(O(n^{\frac{2}{3}})\)
本机4.6s,改小预处理大小又T了...
最后还是用了tangjz的方法,统计\(abc \le n\)的数对个数,规定\(a\le b \le c\),然后a枚举\(n^{\frac{1}{3}}\),b枚举\(\sqrt{\frac{n}{a}}\)。最后乘上\(3!\)再减去\(a= b <c,\ a<b = c,\ a=b=c\)
这一部分的复杂度\(T'(n)=O(\sum_{i=1}^{n^\frac{1}{3}}{\sqrt{\frac{n}{i}}})=O(n^\frac{2}{3})\)
总体复杂度\(T(n)=O(\sum_{d=1}^{\sqrt{n}}{T'(\frac{n}{d^2})})=?O(n^\frac{2}{3})\)
求积分好像是\(\sqrt{n}\)啊,我也不知道这是怎么算的
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;
typedef long long ll;
const int N=320000;
int U=316230;
inline ll read(){
char c=getchar(); ll x=0,f=1;
while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
return x*f;
}
bool notp[N]; int p[N], mu[N];
void sieve(int n) {
mu[1]=1;
for(int i=2; i<=n; i++) {
if(!notp[i]) p[++p[0]] = i, mu[i] = -1;
for(int j=1; j <= p[0] && i*p[j] <= n; j++) {
notp[ i*p[j] ] = 1;
if(i % p[j] == 0) {mu[ i*p[j] ] = 0; break;}
mu[ i*p[j] ] = -mu[i];
}
}
}
inline ll cal(ll n) {
ll ans=0;
for(ll i=1; i*i*i <= n; i++) {
for(ll j=i; i*j*j <= n; j++) {
ans += (n/i/j - j + 1) * 6;
if(i == j) ans -= (n/i/j - j) * 3;
if(i != j) ans -= 3;
}
ans -= 5;
}
return ans;
}
ll solve(ll n) {
ll ans=0;
int m = sqrt(n);
for(int i=1; i<=m; i++) if(mu[i]) ans += mu[i]>0 ? cal(n/i/i) : -cal(n/i/i);
return (ans + n) / 2;
}
int main() {
freopen("in", "r", stdin);
sieve(U);
ll l=read(), r=read();
printf("%lld", solve(r) - solve(l-1));
printf("\n\n%lf\n",(double)clock()/CLOCKS_PER_SEC);
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <ctime>
using namespace std;
typedef long long ll;
const int N=22000005;
int U=22000000;
inline ll read(){
char c=getchar(); ll x=0,f=1;
while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
return x*f;
}
bool notp[N]; int p[N/10], mu[N], lp[N]; ll si[N];
void sieve(int n) {
mu[1]=1; si[1]=1;
for(int i=2; i<=n; i++) {
if(!notp[i]) p[++p[0]] = i, mu[i] = -1, si[i] = lp[i] = 2;
for(int j=1; j <= p[0] && i*p[j] <= n; j++) {
int t = i*p[j];
notp[t] = 1;
if(i%p[j] == 0) {
mu[t] = 0;
lp[t] = lp[i] + 1;
si[t] = si[i] / lp[i] * lp[t];
break;
}
mu[t] = -mu[i];
lp[t] = 2;
si[t] = si[i] * 2;
}
mu[i] += mu[i-1];
si[i] += si[i-1];
}
}
namespace ha {
const int p = 1001001;
struct ha {
struct meow{int ne; ll val, r;} e[10000];
int cnt, h[p];
ha() {cnt=0; memset(h, 0, sizeof(h));}
inline void insert(ll x, ll val) {
int u = x%p;
for(int i=h[u];i;i=e[i].ne) if(e[i].r == x) return;
e[++cnt] = (meow){h[u], val, x}; h[u] = cnt;
}
inline ll quer(ll x) {
int u = x%p;
for(int i=h[u];i;i=e[i].ne) if(e[i].r == x) return e[i].val;
return -1;
}
} hs, hu, me;
} using ha::hs; using ha::hu; using ha::me;
ll dj_u(ll n) { //return 1;
if(n <= U) return mu[n];
if(hu.quer(n) != -1) return hu.quer(n);
ll ans = 1, r;
for(ll i=2; i<=n; i=r+1) {
r = n/(n/i);
ans -= (r-i+1) * dj_u(n/i);
}
hu.insert(n, ans);
return ans;
}
ll dj_s(ll n) {
if(n <= U) return si[n];
if(hs.quer(n) != -1) return hs.quer(n);
dj_u(n);
ll ans = n, r, now, last = dj_u(1);
for(ll i=2; i<=n; i=r+1, last=now) {
r = n/(n/i); now = dj_u(r);
ans -= (now - last) * dj_s(n/i);
}
hs.insert(n, ans);
return ans;
}
ll cal(ll n) {
ll ans=0, r;
for(ll i=1; i<=n; i=r+1) {
r = n/(n/i);
ans += (r-i+1) * dj_s(n/i);
}
return ans;
}
ll solve(ll n) {
ll ans=0;
int m = sqrt(n);
for(ll i=1; i<=m; i++) if(mu[i] - mu[i-1]) ans += (mu[i] - mu[i-1]) * cal(n / (i*i));
return (ans + n) / 2;
}
ll l, r;
int main() {
freopen("in", "r", stdin);
sieve(U);
l=read(); r=read();
//printf("%lld", dj_u(r));
printf("%lld", solve(r) - solve(l-1));
printf("\n\n%lf\n",(double)clock()/CLOCKS_PER_SEC);
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;
typedef long long ll;
const int N=22000005;
int U=22000000;
inline ll read(){
char c=getchar(); ll x=0,f=1;
while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
return x*f;
}
bool notp[N]; int p[N/10], mu[N], lp[N]; ll si[N];
void sieve(int n) {
mu[1]=1; si[1]=1;
for(int i=2; i<=n; i++) {
if(!notp[i]) p[++p[0]] = i, mu[i] = -1, si[i] = lp[i] = 2;
for(int j=1; j <= p[0] && i*p[j] <= n; j++) {
int t = i*p[j];
notp[t] = 1;
if(i%p[j] == 0) {
mu[t] = 0;
lp[t] = lp[i] + 1;
si[t] = si[i] / lp[i] * lp[t];
break;
}
mu[t] = -mu[i];
lp[t] = 2;
si[t] = si[i] * 2;
}
//mu[i] += mu[i-1];
si[i] += si[i-1];
}
}
inline ll g(ll n) { if(n <= U) return si[n];
ll ans=0, r;
for(ll i=1; i<=n; i=r+1) {
r = n/(n/i);
ans += (r-i+1) * (n/i);
}
return ans;
}
ll cal(ll n) {
ll ans=0, r;
for(ll i=1; i<=n; i=r+1) {
r = n/(n/i);
ans += (r-i+1) * g(n/i);
}
return ans;
}
ll solve(ll n) {
ll ans = 0;
int m = sqrt(n);
for(ll i=1; i<=m; i++)
if(mu[i]) ans += mu[i] * cal(n / (i*i));
return (ans + n) / 2;
}
ll l, r;
int main() {
freopen("in", "r", stdin);
sieve(U);
l=read(); r=read();
printf("%lld", solve(r) - solve(l-1));
printf("\n\n%lf\n",(double)clock()/CLOCKS_PER_SEC);
}
51NOD 1222 最小公倍数计数 [莫比乌斯反演 杜教筛]的更多相关文章
- [51nod1227]平均最小公倍数(莫比乌斯反演+杜教筛)
题意 求 $\sum_{i=a}^b \sum_{j=1}^i \frac{lcm(i,j)}{i}$. 分析 只需要求出前缀和, $$\begin{aligned}\sum_{i=1}^n \sum ...
- [复习]莫比乌斯反演,杜教筛,min_25筛
[复习]莫比乌斯反演,杜教筛,min_25筛 莫比乌斯反演 做题的时候的常用形式: \[\begin{aligned}g(n)&=\sum_{n|d}f(d)\\f(n)&=\sum_ ...
- 【bzoj3930】[CQOI2015]选数 莫比乌斯反演+杜教筛
题目描述 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一 ...
- [BZOJ 3930] [CQOI 2015]选数(莫比乌斯反演+杜教筛)
[BZOJ 3930] [CQOI 2015]选数(莫比乌斯反演+杜教筛) 题面 我们知道,从区间\([L,R]\)(L和R为整数)中选取N个整数,总共有\((R-L+1)^N\)种方案.求最大公约数 ...
- 51nod 1237 最大公约数之和 V3【欧拉函数||莫比乌斯反演+杜教筛】
用mu写lcm那道卡常卡成狗(然而最后也没卡过去,于是写一下gcd冷静一下 首先推一下式子 \[ \sum_{i=1}^{n}\sum_{j=1}^{n}gcd(i,j) \] \[ \sum_{i= ...
- 51Nod.1237.最大公约数之和 V3(莫比乌斯反演 杜教筛 欧拉函数)
题目链接 \(Description\) \(n\leq 10^{10}\),求 \[\sum_{i=1}^n\sum_{j=1}^ngcd(i,j)\ mod\ (1e9+7)\] \(Soluti ...
- 51nod 1220 约数之和【莫比乌斯反演+杜教筛】
首先由这样一个式子:\( d(ij)=\sum_{p|i}\sum_{q|j}[gcd(p,q)==1]\frac{pj}{q} \)大概感性证明一下吧我不会证 然后开始推: \[ \sum_{i=1 ...
- 【CCPC-Wannafly Winter Camp Day3 (Div1) F】小清新数论(莫比乌斯反演+杜教筛)
点此看题面 大致题意: 让你求出\(\sum_{i=1}^n\sum_{j=1}^n\mu(gcd(i,j))\). 莫比乌斯反演 这种题目,一看就是莫比乌斯反演啊!(连莫比乌斯函数都有) 关于莫比乌 ...
- [HDU 5608]Function(莫比乌斯反演 + 杜教筛)
题目描述 有N2−3N+2=∑d∣Nf(d)N^2-3N+2=\sum_{d|N} f(d)N2−3N+2=∑d∣Nf(d) 求∑i=1Nf(i)\sum_{i=1}^{N} f(i)∑i=1Nf ...
随机推荐
- qt creator 中的"提升为..."功能简介
1.新建一个项目 2.打开文件:mainwindow.ui ->拖一个 tree widget 控件到画布->右击弹出对话框->单击"提升为..."选项 3.输入 ...
- 2017年 JavaScript 框架回顾 -- React生态系统
前一篇文章中,我们介绍了2017年 JavaScript 框架的整体情况.我们也了解到在众多的前端框架中,目前最为庞大又在快速增长的当属 React 了,本文就来重点介绍 React 的生态系统. 首 ...
- [20160711][在Windows下调用neven链接库]
相关说明 这篇文档是接前篇[20160711][neven代码移植Windows]和[20160711][VS2012配置OpenCV2.4.9]下完成,首先需要通过篇文档编译出neven动态链接库和 ...
- 程序员是这样区分Null和Undefined
Null类型 Null类型是第二个只有一个值的数据类型,这个特殊的值是null.从逻辑角度来看,null值表示一个空对象指针,而这也正是使用typeof操作符检测null值时会返回"obje ...
- UE4 径向模糊radiu blur
hlsl代码为: float2 ScreenMult = ; ; ] = {-0.08,-0.05,-0.03,-0.02,-0.01,0.01,0.02,0.03,0.05,0.08}; float ...
- 织梦dedecsm系统"企业简介"类单栏目模版如何修改和调用
2013-1-12 14:46 | 发布者: moke | 栏目:dedecms教程 我们的模版里应该都有article_article.htm这个模版,这个模版是文章内容页模板,也就是 ...
- electron 学习笔记
一.快速搭建一个electron 项目结构 # 克隆示例项目的仓库 $ git clone https://github.com/electron/electron-quick-start # 进入这 ...
- Red Hat
同义词 REDHAT一般指Red Hat Red Hat(红帽)公司(NYSE:RHT)是一家开源解决方案供应商,也是标准普尔500指数成员.总部位于美国北卡罗来纳州的罗利市,截止2015年3月3日, ...
- 【jsp】MyEclipse10.7.1最新版+破解下载
MyEclipse企业级工作平台[1](MyEclipse Enterprise Workbench ,简称MyEclipse)是对EclipseIDE的扩展,利用它我们可以在数据库和JavaEE的开 ...
- 【笔记】BFC 模型知识整理
网上看了很多 BFC 的概念,发现都说得不是很完整和深入,刚好最近看了一些视频教程说到了 BFC 概念所以记录一下. BFC 的概念: BFC 全称:Block format context 块级格式 ...