zoukankan      html  css  js  c++  java
  • 线性筛

    数论函数

    \(f(n)\) 定义域为 \(N\) (正整数域),值域为 \(N\)
    \(f(x)=x\)\(f(x)=x^2\)

    积性函数

    对于一个函数 \(f(x)\) ,如果 \(\forall a,b,\gcd(a,b)=1,ab=x,f(a)f(b)=f(x)\) ,则称 \(f\) 是积性函数。
    证明约数和函数是积性函数:
    考虑 \(a,b(\gcd(a,b)=1,ab=x)\)
    \(f(a)f(b)=\sum \limits _{d|a}d \sum \limits _{p|b}p= \sum \limits _{d|a}\sum \limits _{p|b}dp\)
    因为 \(\gcd(a,b)=1\) ,所以 \(\gcd(d,p)=1\)
    所以 \(f(a)f(b)=\sum \limits _{d|a}d \sum \limits _{p|b}p=\sum \limits _{d|a}\sum \limits _{p|b}dp=\sum \limits _{(dp)|(ab)}dp\)
    因为 \(ab=x\) ,令 \(t=dp\)
    \(f(a)f(b)=\sum \limits _{t|x}t=f(x)\)

    埃氏筛

    for(int i=2;i<=n;i++)
    	if(p[i]) for(int j=2;i*j<=n;j++) p[i*j]=false;
    

    线性筛

    每个数被它的最小质因子筛掉。

    bool co[N]={false,true};//coprime
    int pn[N],cnt;//prime number
    for(int i=2;i<=n;i++)
    {
    	if(!co[i]) pn[++cnt]=i;
    	for(int j=1;j<=cnt;j++)
    	{
                    //pn[j]是i*pn[j]的最小质因子
    		if(i*pn[j]>n) break;
    		co[i*pn[j]]=true;
    		if(!(i%pn[j])) break;
                    //i=pn[j]*k
                    //如果继续枚举,pn[j+1]*i=pn[j+1]*pn[j]*k
                    //一定已经被 pn[j] 筛过了。
    	}
    }
    

    积性函数筛

    给出 \(n\) ,求 \(f(1),f(2), \cdots ,f(n)\) 。其中 \(f(x)= \sum \limits _{d|x} d\)

    bool co[N]={false,true};//coprime
    int pn[N],f[N]={0,1},cnt;//prime number
    int z[N];//z[i]表示p^c。其中p是i的最小质因子。p^c|i,p^{c+1} not|i
    for(int i=2;i<=n;i++)
    {
    	if(!co[i])
    	{
    		pn[++cnt]=i;
    		f[i]=i+1,z[i]=i;
    	}
    	for(int j=1;j<=cnt;j++)
    	{
    		//pn[j]是i*pn[j]的最小质因子 
    		if(i*pn[j]>n) break;
    		co[i*pn[j]]=true;
    		if(!(i%pn[j]))
    		{
    			int x=i*pn[j];
    			z[x]=z[i]*pn[j];
    			if(z[x]==x) f[x]=f[i]+x;
    			//x是pn[j]的幂。
    			//f[x]=1+pn[j]+pn[j]^2+...+pn[j]^k
    			//i=x/pn[j]
    			//f[i]=1+pn[j]+pn[j]^2+...+pn[j]^{k-1}
    			//f[x]=f[i]+pn[j]^k=f[i]+x 
    			else f[x]=f[x/z[x]]*f[z[x]];
    			//i/pn[j]/pn[j]...
    			//f[i*pn[j]]=f[i]*f[pn[j]^k]
    			
    			//pn[j]是i的最小质因子。
    			//如果继续枚举,pn[j]就不是i*pn[j]的最小质因子了。
    			break;
    		}
    		else
    		{
    			f[i*pn[j]]=f[i]*f[pn[j]];
    			z[i*pn[j]]=pn[j];
    			//i%pn[j]!=0->gcd(i,pn[j])==1
    			//pn[j]是i*pn[j]唯一的最小质因子。
    		}
    	}
    }
    

    三个要点:
    1.质数的情况
    2.\(i \perp p_j\) 的情况(\(a \perp b \Leftrightarrow \gcd(a,b)=1\)
    3.\(p_j\)\(i\) 的最小质因子的情况

    欧拉函数

    \(\varphi(n)\) 表示 \(1\)\(n\) 中与 \(n\) 互质的数的个数。
    \(\varphi(n)=\sum \limits _{i=1}^n [i \perp n]\)
    \(\varphi(n)\) :
    根据整数唯一分解定理,设 \(n=\prod \limits _{i=1}^k p_i^{c_i}\) ( \(p_i\) 是质数),
    \(\varphi(n)=n \prod \limits _{i=1}^k \left (1- \frac{1}{p_i} \right )\)

    莫比乌斯函数

    \(\mu(n)= \begin{cases} 1&n=1\\ (-1)^k&c_i=1\\ 0& \text{otherwise} \end{cases}\)
    证明 \(\mu\) 是积性函数:
    对于 \(\forall a,b,a \perp b,ab=x\) , 考虑 \(\mu(a)\mu(b)\) :
    1.若 \(\mu(a)=0\)\(\mu(b)=0\) ,则 \(ab\) 必含平方因子,则 \(\mu(ab)=\mu(a)\mu(b)=0\)
    2.否则,由于 \(a \perp b\) ,则 \(ab\) 也不含平方因子,则 \(\mu(a)\mu(b)=(-1)^{k_1}(-1)^{k_2}=(-1)^{k_1+k_2}=\mu(ab)\)

    一般线性筛

    对于一个积性函数 \(f\) ,考虑以下的线性筛法:
    要计算 \(f(n)\) ,考虑到 \(n=\prod \limits _{i=1}^k p_i^{c_i}\)
    在线性筛的过程中,如果 \(i \bmod p_j \neq 0\) ,就有 \(f(i \cdot p_j)=f(i)f(p_j)\)
    否则,考虑 \(k|(i \cdot p_j)\)\(k \perp p_j\) ,则有 \(f(i \cdot p_j)=f(k)f( \frac{i \cdot p_j}{k})\)
    因此,我们只需要记录对于每一个 \(i \cdot p_j\) 对应的 \(k\) ,和推导出从 \(f(p^c)\)\(f(p^{c+1})\) 的关系式即可。

    一个例题

    \(f(i)\) 表示有序三元组 \((a,b,c)\) 的个数,使得 \(abc=i\) 。求出 \(f(1)\) ~ \(f(n)\)\(n \leq 10^7\)
    证明 \(f\) 是积性函数
    写出式子: \(f(i)=\sum \limits_{a|i} \sum \limits_{b|i} \sum \limits_{c|i} [abc=i]\)
    显然,原式等于 \(\sum \limits_{a|i} \sum \limits_{b| \frac{i}{a}} 1\)
    \(d(n)\) 表示 \(n\) 的约数个数,
    则原式可转化为 \(\sum \limits_{a|i} d(\frac{i}{a})\)
    \(\sum \limits_{a|i} d(a)\)
    所以,要先证明 \(d\) 是积性函数。
    \(d(a)d(b)=\sum \limits_{x|a} 1 \sum \limits_{y|b} 1\)
    因为 \(a \perp b\) ,所以 \(x \perp y\)
    所以原式等于 \(\sum \limits_{(xy)|(ab)} 1\)
    所以 \(d(a)d(b)=d(ab)\)
    所以 \(d\) 是积性函数。
    所以 \(f(a)f(b)=\sum \limits_{x|a} d(x) \sum \limits_{y|b} d(y)\)
    因为 \(a \perp b\) ,所以 \(x \perp y\)
    所以原式等于 \(\sum \limits_{(xy)|(ab)} d(x)d(y)\)
    因为 \(d\) 是积性函数,
    所以原式等于 \(\sum \limits_{(xy)|(ab)} d(xy)\)
    所以 \(f(a)f(b)=f(ab)\)
    所以 \(f\) 是积性函数。
    所以就可以开始筛了。

    考虑 \(f(p^k)\)
    \(a=p^x\)\(b=p^y\)\(c=p^z\)
    那么 \(k=x+y+z\)
    用插板法可求出方案为 \(C(k+2,2)\)
    筛的时候记一下 \(k\) 即可。

  • 相关阅读:
    D365: 笔记(VS无法打开表浏览器)
    D365: 笔记(跟踪调试批处理代码)
    D365: 笔记(非批处理执行class中弹出交互式窗体或报表)
    D365: 笔记(现有量增加批号表字段查询条件)
    D365: 新功能(二)采购发票自动化流程
    D365: 新功能(一)按日期设置编号规则
    ES6 入门教程(未完)
    深入理解TypeScript(未完)
    项目
    vue + threejs 项目踩坑总结
  • 原文地址:https://www.cnblogs.com/zhs1/p/12693917.html
Copyright © 2011-2022 走看看