[bzoj 4176] Lucas的数论 (杜教筛 + 莫比乌斯反演)
题面
设d(x)d(x)d(x)为xxx的约数个数,给定NNN,求 ∑i=1N∑j=1Nd(ij)\sum^{N}_{i=1}\sum^{N}_{j=1} d(ij)i=1∑Nj=1∑Nd(ij)
N<=109N<=10^9N<=109
题目分析
有这样一个结论
d(ij)=∑x∣i∑y∣j[(x,y)==1]d(ij)=\sum_{x|i}\sum_{y|j}[(x,y)==1]d(ij)=x∣i∑y∣j∑[(x,y)==1]这道题就是下面这道题的数据增强版,那么这个结论的证明就不再赘述,请自行查看下面的(蒟蒻)博客 传送门:[SDOI2015][bzoj 3994][Luogu P3327] 约数个数和
Ans=∑k=1Nμ(k)(∑x=1⌊Nk⌋⌊Nkx⌋)2\large Ans=\sum_{k=1}^N\mu(k)\left(\sum_{x=1}^{⌊\frac{N}{k}⌋}⌊\frac{N}{kx}⌋\right)^2Ans=k=1∑Nμ(k)⎝⎜⎛x=1∑⌊kN⌋⌊kxN⌋⎠⎟⎞2
由于数据范围的增强,我们不能预处理完整个10910^9109,于是就外层整除分块优化
- 内层杜教筛来算μ\muμ的前缀和,时间复杂度为Θ(N23)\Theta (N^{\frac 23})Θ(N32)
- 后面平方的底数实际上等于[1,⌊Nk⌋]\left[1,⌊\frac{N}{k}⌋\right][1,⌊kN⌋]的约数个数和的前缀和,可以直接Θ(⌊Nk⌋)\Theta(\sqrt {⌊\frac{N}{k}⌋})Θ(⌊kN⌋)算,预处理出前N23N^{\frac23}N32的约数个数和的前缀和后,总时间复杂度就如杜教筛一样为Θ(N23)\Theta(N^\frac 23)Θ(N32)
总时间复杂度为Θ(N23)\Theta (N^{\frac 23})Θ(N32)
AC code
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
typedef long long LL;
const int N = 1e6 + 1;
const int mod = 1e9 + 7;
int Cnt, Prime[N], mu[N], d[N], a[N]; //a[i]存的是i的最小质因数的次数+1
bool IsnotPrime[N];
void init()
{
mu[1] = d[1] = a[1] = 1;
for(int i = 2; i < N; ++i)
{
if(!IsnotPrime[i])
Prime[++Cnt] = i, mu[i] = -1, a[i] = d[i] = 2;
for(int j = 1; j <= Cnt && i * Prime[j] < N; ++j)
{
IsnotPrime[i * Prime[j]] = 1;
if(i % Prime[j] == 0)
{
mu[i * Prime[j]] = 0;
d[i * Prime[j]] = d[i] / a[i] * (a[i * Prime[j]] = a[i] + 1);
break;
}
mu[i * Prime[j]] = -mu[i];
d[i * Prime[j]] = d[i] * (a[i * Prime[j]] = 2);
}
}
for(int i = 1; i < N; ++i)
(d[i] += d[i-1]) %= mod, (mu[i] += mu[i-1]) %= mod;
}
inline int sum_d(int n) //约数个数和的前缀和,也就是后面个平方的底数
{
if(n < N) return d[n];
int ret = 0;
for(int i = 1, j; i <= n; i=j+1)
{
j = n/(n/i);
ret = (ret + (LL)(n/i) * (j-i+1) % mod) % mod;
}
return ret;
}
map<int, int>s;
inline int sum_mu(int n)
{
if(n < N) return mu[n];
if(s.count(n)) return s[n];
int ret = 1;
for(int i = 2, j; i <= n; i=j+1)
{
j = n/(n/i);
ret = (ret - (LL)sum_mu(n/i)*(j-i+1)%mod) % mod;
}
return s[n]=ret;
}
int solve(int n)
{
int ret = 0, last = 0, tmp, tmp2;
for(int i = 1, j; i <= n; i=j+1)
{
j = n/(n/i);
tmp = sum_mu(j), tmp2 = sum_d(n/i), tmp2 = (LL)tmp2 * tmp2 % mod;
//tmp2存后面那个平方的值
ret = (ret + (LL)((tmp-last) % mod) * tmp2 % mod) % mod;
last = tmp;//这利用了一个小优化,本来是sum_mu(j)-sum_mu(i-1),
//我们把sum_mu(i-1)的值存下来,就少计算一次,last存上一次答案
//然而我后来看发现这优化并没有什么卵用,本来就记忆化了...
}
return ret;
}
int main ()
{
init(); int n;
scanf("%d", &n);
printf("%d\n", (solve(n)+mod)%mod);
}
.
.
.
少有的一A
二刷:bzoj rank 7
CODE
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1000005;
const int mod = 1e9 + 7;
int prime[MAXN/10], cnt, mu[MAXN], d[MAXN], a[MAXN];
bool vis[MAXN];
inline void Pre_Work(int n) {
mu[1] = d[1] = a[1] = 1;
for(int i = 2; i <= n; ++i) {
if(!vis[i])
prime[++cnt] = i, mu[i] = -1, d[i] = a[i] = 2;
for(int j = 1; j <= cnt && i*prime[j] <= n; ++j) {
vis[i*prime[j]] = 1;
if(i % prime[j] == 0) {
mu[i*prime[j]] = 0;
d[i*prime[j]] = d[i] / a[i] * (a[i*prime[j]] = a[i]+1);
break;
}
mu[i*prime[j]] = -mu[i];
d[i*prime[j]] = d[i] * (a[i*prime[j]] = 2);
}
}
for(int i = 2; i <= n; ++i)
mu[i] += mu[i-1], (d[i] += d[i-1]) %= mod;
}
map<int, int>MU;
inline int sum_mu(int n) {
if(n < MAXN) return mu[n];
if(MU.count(n)) return MU[n];
int re = 1;
for(int i = 2, j; i <= n; i = j+1) {
j = n/(n/i);
re = (re - 1ll * (j-i+1) * sum_mu(n/i) % mod) % mod;
}
return MU[n]=re;
}
map<int, int>D;
inline int sum_d(int n) {
if(n < MAXN) return d[n];
if(D.count(n)) return D[n];
int re = 0;
for(int i = 1, j; i <= n; i = j+1) {
j = n/(n/i);
re = (re + 1ll * (j-i+1) * (n/i) % mod) % mod;
}
return D[n]=re;
}
inline int sqr(int x) { return 1ll*x*x%mod; }
inline int solve(int n) {
int re = 0;
for(int i = 1, j; i <= n; i = j+1) {
j = n/(n/i);
re = (re + 1ll * (sum_mu(j)-sum_mu(i-1)) % mod * sqr(sum_d(n/i)) % mod) % mod;
}
return re;
}
int main() {
int n;
scanf("%d", &n);
Pre_Work(min(n, MAXN-1));
printf("%d\n", (solve(n) + mod) % mod);
}
[bzoj 4176] Lucas的数论 (杜教筛 + 莫比乌斯反演)的更多相关文章
- BZOJ 4176: Lucas的数论 [杜教筛]
4176: Lucas的数论 题意:求\(\sum_{i=1}^n \sum_{j=1}^n \sigma_0(ij)\) \(n \le 10^9\) 代入\(\sigma_0(nm)=\sum_{ ...
- bzoj 4176: Lucas的数论 -- 杜教筛,莫比乌斯反演
4176: Lucas的数论 Time Limit: 30 Sec Memory Limit: 256 MB Description 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么 ...
- 【XSY2731】Div 数论 杜教筛 莫比乌斯反演
题目大意 定义复数\(a+bi\)为整数\(k\)的约数,当且仅当\(a\)和\(b\)为整数且存在整数\(c\)和\(d\)满足\((a+bi)(c+di)=k\). 定义复数\(a+bi\)的实部 ...
- 【BZOJ4176】Lucas的数论-杜教筛
求$$\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}f(ij)$$,其中$f(x)$表示$x$的约数个数,$0\leq n\leq 10^9$,答案膜$10^9+ ...
- BZOJ_4176_Lucas的数论_杜教筛+莫比乌斯反演
BZOJ_4176_Lucas的数论_杜教筛+莫比乌斯反演 Description 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目“求 ...
- bzoj4176. Lucas的数论 杜教筛
题意:求\(\sum_{i=1}^n\sum_{j=1}^nd(ij),d是约数个数函数\) 题解:首先有一个结论\(d(ij)=\sum_{x|i}\sum_{y|j}[(i,j)==1]\) 那么 ...
- [CQOI2015][bzoj3930] 选数 [杜教筛+莫比乌斯反演]
题面: 传送门 思路: 首先我们把区间缩小到$\left[\lfloor\frac{L-1}{K}\rfloor,\lfloor\frac{R}{K}\rfloor\right]$ 这道题的最特殊的点 ...
- [51Nod 1237] 最大公约数之和 (杜教筛+莫比乌斯反演)
题目描述 求∑i=1n∑j=1n(i,j) mod (1e9+7)n<=1010\sum_{i=1}^n\sum_{j=1}^n(i,j)~mod~(1e9+7)\\n<=10^{10}i ...
- bzoj 4916: 神犇和蒟蒻 (杜教筛+莫比乌斯反演)
题目大意: 读入n. 第一行输出“1”(不带引号). 第二行输出$\sum_{i=1}^n i\phi(i)$. 题解: 所以说那个$\sum\mu$是在开玩笑么=.= 设$f(n)=n\phi(n) ...
随机推荐
- [转帖]SSD和内存数据库技术
SSD和内存数据库技术 自己的理解还是不是很对 SSD 提升的是 随机读 并没有对顺序写有多大的提升, 因为数据库采用的是redo的模式. 理论上写入 时是顺序写 所以 写并发的提升不会很大 但是会很 ...
- C++中STL中简单的Vector的实现
该vector只能容纳标准库中string类, 直接上代码了,StrVec.h文件内容为: #ifndef STRVEC_H #define STRVEC_H #include<iostream ...
- c++11多线程记录4:死锁
简单示例 举个例子,桌上有一支笔和一张纸,小A和小B都要拿到纸笔写字 小A拿了笔,小B拿了纸,这时就形成了死锁(两人都不愿意让出纸笔). 其实只要稍加控制就可以避免这种情况:规定必须先拿到纸再能去尝试 ...
- (六)pdf的构成之文件体(pages对象)
页面树(pages) 通过页面树访问文档的页面,页面树定义PDF文档中的所有页面.树包含表示PDF文档页面的节点,可以是两种类型:中间节点和叶节点.中间节点也称为页面树节点,而叶节点称为页面对象.最简 ...
- golang 之 jwt-go
主要针对jwt-go快速生成token.和如何取进行介绍,具体详情还请查看 github.com/dgrijalva/jwt-go 生成token package main import ( &quo ...
- Java 随机数生成工具RandomUtils
RandomUtils /** * <html> * <body> * <P> Copyright 1994 JsonInternational</p> ...
- C#设计模式之11:命令模式
C#设计模式之11:命令模式 命令模式 命令模式用来解决一些复杂业务逻辑的时候会很有用,比如,你的一个方法中到处充斥着if else 这种结构的时候,用命令模式来解决这种问题就会让事情变得简单很多. ...
- Python 将中文、字母转成数字
Outline 把中文汉字或者英文字母或者特殊字符转换成数字. (实质是字符转成对应ASCII码) 转换 将中文汉字转成数字: ord('单个中文汉字') 反转: chr(21704) 将英文字母转成 ...
- XXL-JOB使用命令行的方式启动python时,日志过多导致阻塞的解决方式
一.Runtime.getRuntime().exec()的阻塞问题 这个问题也不能算是XXL-JOB的问题,而是Java的Runtime.getRuntime().exec()造成的,Buffere ...
- webpack集成vue单文件模式的很多坑(研究了1个星期)
1.一开始不知道局部安装webpack后,如何调用webpack. 后来看说明文档(webpack中文网)才知道,有个npx可以启动本地安装的webpack. 我估计:全局安装webpack,全局的w ...