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(k) = \sum_{n=1}^k \sigma _0 (n^2) =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(\sum_{p=1}^{\sqrt n} \sum_{i=1}^{\sqrt[3]{\frac{n}{p^2}}} \lfloor \frac{n}{p^2i}\rfloor) $$

$$O(\sum_{i=1}^{\sqrt[3]{n}} \frac n i) = O(\int _{1}^{\sqrt[3]{n}} \frac n x {\rm d} x)=O(n\int _{1}^{\sqrt[3]{n}} x^{-1} {\rm d} x)$$

代码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;
}

  

原文地址:https://www.cnblogs.com/zhouzhendong/p/51Nod1222.html

时间: 2024-10-09 07:20:24

51Nod1222 最小公倍数计数 数论 Min_25 筛的相关文章

51nod1222 最小公倍数计数

题目来源: Project Euler 基准时间限制:6 秒 空间限制:131072 KB 分值: 640 定义F(n)表示最小公倍数为n的二元组的数量. 即:如果存在两个数(二元组)X,Y(X <= Y),它们的最小公倍数为N,则F(n)的计数加1. 例如:F(6) = 5,因为[2,3] [1,6] [2,6] [3,6] [6,6]的最小公倍数等于6. 给出一个区间[a,b],求最小公倍数在这个区间的不同二元组的数量. 例如:a = 4,b = 6.符合条件的二元组包括: [1,4] [2

【51nod】1222 最小公倍数计数 莫比乌斯反演+组合计数

[题意]给定a和b,求满足a<=lcm(x,y)<=b && x<y的数对(x,y)个数.a,b<=10^11. [算法]莫比乌斯反演+组合计数 [题解]★具体推导过程参考:51nod1222 最小公倍数计数 过程运用到的技巧: 1.将所有i和j的已知因子提取出来压缩上届. 2.将带有μ(k)的k提到最前面,从而后面变成单纯的三元组形式. 最终形式: $$ans=\sum_{k=1}^{\sqrt n} \mu(k)  \sum_{d}    \sum_{i} \s

SP34096 DIVCNTK - Counting Divisors (general) min_25筛

\(\color{#0066ff}{ 题目描述 }\) \(σ_0(i)\) 表示\(i\) 的约数个数 求\(S_k(n)=\sum_{i=1}^n\sigma_0(i^k)\mod 2^{64}\) \(\color{#0066ff}{输入格式}\) 第一行一个T为数据组数 接下来每组数据一个n,一个k \(\color{#0066ff}{输出格式}\) 每个询问输出一行 \(\color{#0066ff}{输入样例}\) 5 1 3 2 3 3 3 10 3 100 3 \(\color{

P4213 【模板】杜教筛(Sum) min_25筛

\(\color{#0066ff}{ 题目描述 }\) 给定一个正整数\(N(N\le2^{31}-1)\) 求 \(ans_1=\sum_{i=1}^n\varphi(i)\) \(ans_2=\sum_{i=1}^n \mu(i)\) \(\color{#0066ff}{输入格式}\) 一共T+1行 第1行为数据组数T(T<=10) 第2~T+1行每行一个非负整数N,代表一组询问 \(\color{#0066ff}{输出格式}\) 一共T行,每行两个用空格分隔的数ans1,ans2 \(\c

UOJ188. 【UR #13】Sanrd [min_25筛]

传送门 思路 也可以算是一个板题了吧qwq 考虑min_25筛最后递归(也就是DP)的过程,要枚举当前最小的质因子是多少. 那么可以分类讨论,考虑现在这个质因子是否就是次大质因子. 如果不是,那么就是\(S(n/p,k+1)\):如果是,那么剩下的必定是一个更大的质数,那么就需要知道一段区间内有多少个质数. 质数个数显然可以min_25筛给搞出来. 于是就做完了. 代码 #include<bits/stdc++.h> clock_t t=clock(); namespace my_std{ u

LG5325 【模板】Min_25筛

P5325 [模板]Min_25筛 题目背景 模板题,无背景. 题目描述 定义积性函数$f(x)$,且$f(p^k)=p^k(p^k-1)$($p$是一个质数),求 $$\sum_{i=1}^n f(x)$$ 对$10^9+7$取模. 输入输出格式 输入格式: 一行一个整数$n$. 输出格式: 一个整数表示答案. 输入输出样例 输入样例#1: 复制 10 输出样例#1: 复制 263 输入样例#2: 复制 1000000000 输出样例#2: 复制 710164413 说明 $f(1)=1,f(

ZOJ The Sum of Unitary Totient (Min_25筛)

题意: 给你一个函数f(n)=(p1a1-1)(p2a2-1)...(prar-1) ,n=p1a1p2a2...prar  求\[\sum\limits_{i = 1}^n {f(i)} \],\[n <  = 1e9\] 思路: \[f(p) = p - 1,f({p^k}) = {p^k} - 1\],直接用min_25筛就可以了,按道理来讲我感觉min_25筛是稳过的,但我交了几十次才过,要不是在网上看到有人用min_25筛过了我还以为我想错了 #include<bits/stdc++

数论线性筛总结 (素数筛,欧拉函数筛,莫比乌斯函数筛,前n个数的约数个数筛)

线性筛 线性筛在数论中起着至关重要的作用,可以大大降低求解一些问题的时间复杂度,使用线性筛有个前提(除了素数筛)所求函数必须是数论上定义的积性函数,即对于正整数n的一个算术函数 f(n),若f(1)=1,且当a,b互质时f(ab)=f(a)f(b),在数论上就称它为积性函数,若a,b不互质也满足的话则称作完全积性函数,下面说明每个筛子是怎么筛的. 最基础的是素数筛,其它三个筛都是以素数筛为前提 素数筛 void get_prime() { int pnum = 0; for(int i = 2;

奇怪的数学题(51nod1847)——min_25筛+杜教筛+第二类斯特林数

题面 51nod1847 解析   定义$f(i)$为$i$的次大因数,特别地$f(1)=0$  那么我们就是去求$$\sum_{i=1}^{n}\sum_{j=1}^{n}f^{m}(gcd(i, j))$$ 这种东西的套路就是枚举$gcd$然后用欧拉函数处理, \begin{align*}\sum_{i=1}^{n}\sum_{j=1}^{n}f^{m}(gcd(i, j)) &= \sum_{i=1}^{n}\sum_{j=1}^{\left \lfloor \frac{n}{i}\rig