Min25 筛与 Powerful Numbers

Min25 筛

大喊一声 Min25 NB!!!

这是一个非常神奇的东西,用于求更加普遍的积性函数的前缀和。

比如我们要求 \(\sum_{i=1}^{n}f(i)\),其中 \(f(1)=1\)。我们考虑将质数与合数分开考虑。(由于 \(1\) 这俩都不是,我们先不考虑)所以答案就等于质数的答案加上合数的答案再加上 \(f(1)\)。

但是这样还是不够优美。因为合数的范围太广泛了,我们考虑对于每个质数再分组。

在这里,我们设 \(\sigma(x)\) 为 \(x\) 的最小质因子。

定义 \(S(n,k)\) 表示第 \(2\) 到第 \(n\) 个数中,\(\sigma (x) \ge pri_k\) 的数的 \(f(x)\) 之和。其中 \(p_k\) 表示第 \(k\) 大的质数。显然有 \(\max{p_k}\le \sqrt n\)。这也决定了用到的质数不会很多。

我们同样将质数和合数分开考虑。由于 \(f\) 是积性函数,所以有 \(f(p_1^{k_1})f(p_2^{k^2})=f(p_1^{k_1}p_2^{k^2})\)。这启发我们可以枚举质数幂进行转移。

所以有

\[S(n,k)=\sum_{i\ge k,p_i\le n}f(p_i)+\sum_{j\ge k}\sum_{e\ge 1,p_j^{e+1}\le n}(f(p_j^e)\cdot S(\lfloor\frac{n}{p_j^e}\rfloor,j+1)+f(p_j^{e+1}))
\]

稍微解释一下就是前半部分是满足条件的质数的和。 \(S(\lfloor\frac{n}{p_j^e}\rfloor,j+1)\) 中的数的最小质因子 \(\ge p_{j+1}>p_j\),所以这里我们枚举一个没有出现过的质数幂乘上去。同时由于 \(f\) 是积性函数,我们要对这一部分值全部乘上 \(f(p_j^e)\)。同时注意答案中没有包含 \(f(p_j^{e+1})\) 这一项(因为我们是从 \(2\) 开始计数的,在前面做乘法的时候由于 \(1\) 的缺失导致 \(p_j^e\) 的缺失),要补上。

最后的答案就是 \(S(n,1)+f(1)\)。

这个东西可以递归进行计算,但是显然需要一些条件:

  • \(f(p)\) 是一个关于 \(p\) 的项数较小的多项式或可以快速求值。
  • \(f(p^c)\) 能够较方便的计算,即质数幂处的 \(f\) 值能够较方便的计算。
  • \(\sum_{i\ge k,p_i\le n}f(p_i)\) 能够快速计算。然后这东西可以拆成前缀和然后作差。\(i\le k\) 的部分由于 \(k\) 很小,且 \(f(p)\) 是低次多项式,可以在线性筛的时候顺便处理掉,问题转化为快速求出当 \(n\) 较大时质数处的 \(f\) 的前缀和。

第一个和第二个条件我们似乎没有什么办法克服,全看出题人是否良心。

我们来考虑能否快速求出质数处的 \(f\) 的前缀和,设 \(sum_k=\sum_{p\le k,p\in \mathrm{prime}}f(p)\)。

首先对上面的递推式进行观察,会发现我们需要的 \(sum_k\) 的个数其实很少,都是形如 \(sum_{\lfloor\frac n x \rfloor}\) 这样的值。

显然可以证明这样的下标最多只有 \(O(\sqrt n )\) 个,实在不放心可以打个表试试。

然后我们发现,此时我们对于合数的值并不关心,即我们只需要构造一个 \(g\) 使得 \(g(p)=f(p)\),求出 \(g\) 的前缀和后再将合数位置处的 \(g\) 的值剪掉,同样能够得到我们想要得到答案。

我们可以通过构造使得 \(g\) 是一个完全积性函数,即对于任意 \(i,j\) 均有 \(g(i)g(j)=g(ij)\)。

设 \(G(n,k)\) 表示 \(\forall x\in [2,n],x\in \mathrm{prime} \or \sigma(x)> p_k\) 这样的 \(x\) 的 \(g(x)\) 之和。其实这个状态非常类似与我们在进行埃氏筛的时候,枚举到第 \(k\) 个质数且该轮已筛完的状态。

于是我们枚举当前应该筛掉哪些数,有

\[G(n,k)=G(n,k-1)-g(p_k)(G(\lfloor \frac{n}{p_k}\rfloor,k-1)-sum_{p_{k-1}})
\]

我们当前要筛掉 \(\sigma (x)=p_k\) 的合数。

当 \(p_k^2\ge n\) 时,显然我们无数可筛。此时 \(G(n,k)=G(n,k-1)\)。

当 \(p_k^2\le n\) 时,由于我们构造了 \(g\) 使其为完全积性函数,所以减掉 \(g(p_k)G(\lfloor \frac{n}{p_k}\rfloor,k-1)\),就相当于减掉了这一部分合数的 \(g(x)\) 之和。但是根据定义,\(G(\lfloor \frac{n}{p_k}\rfloor,k-1)\) 包含了一部分 \(\le p_k\) 的质数,这样会使得 \(\sigma (x)\neq p_k\),所以要加上 \(g(p_k)sum_{p_{k-1}}\)。

显然答案为 \(G(n,\mathrm{cnt})\),其中 \(\mathrm{cnt}\) 为 \(\le \sqrt n\) 的质数个数。

然后根据前文所提到的,我们最后需要的只有 \(O(\sqrt n)\) 个 \(G(N,\mathrm{cnt})\),直接做就完事了。

初始状态也非常显然:\(G(n,0)=\sum_{i=1}^{n}g(i)\)。

所以我们构造的这个函数应该需要比较好算。

事实上若 \(f(x)\) 是一个 \(k\) 次多项式,我们有\(f(x)=\sum_{i=0}^ka_ix^i\)。

我们把 \(f(x)\) 拆开,令 \(g_k(x)=x^k\),则有 \(f(x)=\sum_{i=0}^ka_ig_i(x)\)。

显然每一个 \(g_k\) 都是一个完全积性函数,而且它的前缀和也非常好算(拉格朗日插值即可),所以我们对每一个 \(g_k\) 筛一遍再合并即可。

Q:如果 k 很大咋办呢?

A:k 很大... k 很大...... 自求多福。——zzq

然后我们就做完了。

我也不太会证明复杂度,反正就能跑 \(10^{10}\),\(10^{11}\) 可以抢救一下。

实际上这个算法比杜教筛快,限制还比杜教筛小。

杜教筛,永远的垃圾。——zzq

「LOJ 6053」 简单的函数

模板题。对于所有奇质数 \(p\),有 \(f(p)=p-1\)。我们先令 \(f(p)=p\) 然后再减掉素数个数即可。

同时注意考虑唯一的偶质数 \(2\) 的贡献。

/*---Author:HenryHuang---*/
/*---Never Settle---*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=5e5+5;
const ll p=1e9+7;
const ll inv2=5e8+4;
ll n,P;
ll pri[maxn],pp[maxn],cnt;
ll id[maxn],id2[maxn],dex;
ll w[maxn],g[maxn],h[maxn],f[maxn];
ll pre[maxn];
ll F(ll x,ll y){
return x^y;
}
void init(){
for(ll i=2;i<=P;++i){
if(!pp[i]) pri[++cnt]=i,pre[cnt]=(pre[cnt-1]+i)%p;
for(ll j=1;j<=cnt&&pri[j]*i<=P;++j){
pp[pri[j]*i]=1;
if(i%pri[j]==0) break;
}
}
} ll getid(ll x){
if(x<=P) return id[x];
else return id2[n/x];
}
void prework(){
for(ll l=1,r,v;l<=n;l=r+1){
v=(n/l),r=(n/v);
if(v<=P) id[v]=++dex;
else id2[r]=++dex;
w[dex]=v;v%=p;
g[dex]=1ll*(2+v)*(v-1+p)%p*inv2%p;
h[dex]=(v-1);
}
for(ll i=1;i<=cnt;++i){
ll z=pri[i];
for(ll j=1;j<=dex&&z*z<=w[j];++j){
ll op=getid(w[j]/z);
g[j]=(g[j]-z*(g[op]-pre[i-1]+p)%p+p)%p;
h[j]=(h[j]-h[op]+i-1+p)%p;
}
}
for(ll j=1;j<=dex;++j) f[j]=(g[j]-h[j]+p)%p;
}
ll solve(ll x,ll i){
if(x<=1||pri[i]>x) return 0;
ll ans=f[getid(x)]-(pre[i-1]-(i-1));
if(i==1) ans+=2;
for(ll j=i;j<=cnt&&pri[j]*pri[j]<=x;++j){
ll r=pri[j];
for(ll e=1;r*pri[j]<=x;++e,r*=pri[j]){
ans=(ans+F(pri[j],e)*solve(x/r,j+1)+F(pri[j],e+1))%p;
}
}
return ans;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;P=sqrt(n+0.5);
init();
prework();
cout<<(solve(n,1)+1)%p<<'\n';
return 0;
}


Powerful Numbers

这也是一个非常神奇的东西,用于求极为特殊的积性函数的前缀和。

比如我们要求 \(\sum_{i=1}^{n}f(i)\),但是这个 \(f\) 非常神奇,其满足 \(f(1)=1,f(p)=1\),其中 \(p\) 为质数。

然后我们发现这和我们一个非常喜欢的积性函数 \(g(x)=1\) 非常像,大家都会求它的前缀和。它们在质数处的值是一样的,即 \(f(p)=g(p)\)。

我们尝试构造一个积性函数 \(h(x)\) 使得 \(\sum_{ij=x}h(i)g(j)=f(x)\)。

首先由 \(f(1)=1\) 可推出 \(h(1)=1\)。

再由 \(f(p)=1\) 可以推出 \(f(p)=h(1)g(p)+h(p)g(1)=1+h(p)\)。

从这里我们发现 \(h(p)=0\),也就是说,\(h\) 在质数位置上的值均为 \(0\)。

再进一步,由于 \(h\) 是一个积性函数,由 \(h(p_ip_j)=h(p_i)h(p_j)\) 有 \(h\) 在所有存在一个质数因子的次数 \(=1\) 的位置均为 \(0\)。

换句话说,只有当一个数,其包含的所有质因子的次数均 \(\ge 2\),\(h\) 才会有值。而这样的数,就被称为 \(\texttt{Powerful Numbers}\)。

可以证明其个数为 \(O(\sqrt n)\) 的。你实在不放心可以打个表跑一跑。

如何求?枚举质因子爆搜就完事了,但需要注意必要的剪枝。

由于 \(\texttt{Powerful Numbers}\) 有这样美好的性质,我们可以把原来的式子转换一下:

\[\begin{aligned}
&\sum_{x=1}^nf(x)\\
=&\sum_{x=1}^n\sum_{ij=x}h(i)g(j)\\
=&\sum_{i=1}^nh(i)\sum_{j=1}^{\lfloor \frac n i \rfloor}g(j)
\end{aligned}
\]

本质上我们需要求出所有 \(ij\le n\) 的 \(h(i)g(j)\),所以换个方式枚举即可。

现在我们的问题就变成了:求 \(\texttt{Powerful Numbers}\) 的 \(h(x)\),以及求 \(g\) 的前缀和。

在这个例子中,\(g\) 的前缀和大家都会求。即 \(\sum_{i=1}^ng(i)=n\)。

问题变为如何快速求出 \(h(x)\)。

事实上你经常可以通过质数幂处的 \(f(p^c)\) 来猜出 \(h(p^c)\) 的值,又因为其是一个积性函数,你就能在爆搜的同时把答案求出来了。

事实上如果你猜不出来可能需要把质数幂处的值全部整出来然后暴力多项式除法?

不管能猜就猜猜不出来再说

总结一下,能够用这种筛法的条件

  • 你能构造出一个积性函数 \(g\) 使得 \(f(p)=g(p)\)。
  • 这个 \(g\) 的前缀和比较好算。

Example

令 \(f(x)=p_1^{\lfloor \frac{c_1}{2}\rfloor}p_2^{\lfloor \frac{c_2}{2}\rfloor}\cdots p_k^{\lfloor \frac{c_k}{2}\rfloor}\),其中 \(p\) 为对 \(x\) 唯一分解后的质因子,\(c\) 为每个质因子的次数。求 \(\sum_{i=1}^nf(i)\)。


我们发现这东西显然是满足 \(f(p)=1\) 的,所以非常愉快地令 \(g(x)=1\)。

现在问题转变为求 \(h(x)\)。

我们多列几项:

\[\begin{aligned}
f(1)=h(1)g(1)&\rightarrow h(1)=1\\
f(p)=h(1)g(p)+h(p)g(1)&\rightarrow h(p)=0\\
f(p^2)=h(1)g(p^2)+h(p)g(p)+h(p^2)g(1)&\rightarrow h(p^2)=p-1\\
f(p^3)=h(1)g(p^3)+h(p)g(p^2)+h(p^2)g(p)+h(p^3)g(1)&\rightarrow h(p^3)=0\\
f(p^4)=h(1)g(p^4)+h(p)g(p^3)+h(p^2)g(p^2)+h(p^3)g(p)+h(p^4)g(1)&\rightarrow h(p^4)=p^2-p=p(p-1)\\
\end{aligned}
\]

我觉得列到这里已经差不多能猜出来了。

当 \(k\) 为奇数时,\(h(p^k)=0\)。

当 \(k\) 为 \(2\) 时,\(h(p^k)=p-1\)。

当 \(k\) 为其他偶数时,\(h(p^k)=(p-1)p^{\frac{k-2}{2}}\)。

然后算就完事了。

时间复杂度为 \(O(\sqrt n )\)。事实上由于当 \(k\) 是奇数时 \(h(p^k)\) 均为 \(0\),所以可以进一步剪枝。

/*---Author:HenryHuang---*/
/*---Never Settle---*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=3.5e6+5;
typedef unsigned long long ll;
ll pri[maxn],pp[maxn],p,cnt;
void init(){
for(ll i=2;i<=p;++i){
if(!pp[i]) pri[++cnt]=i;
for(ll j=1;j<=cnt&&pri[j]*i<=p;++j){
pp[pri[j]*i]=1;
if(i%pri[j]==0) break;
}
}
}
ll ans,n,owo;
void dfs(ll num,ll now,ll phi){
if(now==cnt+1||num*pri[now]>n||num*pri[now]*pri[now]>n){
ans+=phi*(n/num);
++owo;
return ;
}
dfs(num,now+1,phi);
for(int i=2;;i+=2){
num*=pri[now];
if(num>n) break;
num*=pri[now];
if(num>n) break;
if(i==2) phi*=(pri[now]-1);
else phi*=pri[now];
dfs(num,now+1,phi);
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int T;cin>>T;
p=sqrt(1e13);
init();
while(T--){
cin>>n;ans=0;
dfs(1,1,1);
cout<<ans<<'\n';
}
return 0;
}

Submit Link

Min25 筛与 Powerful Numbers的更多相关文章

  1. CodeForces - 83D:Numbers (数学&递归 - min25筛 )

    pro:给定三个整数L,R,P求[L,R]区间的整数有多少个是以P为最小因子的.L,R,P<2e9; sol: 一: 比较快的做法是,用函数的思想递归. 用solve(N,P)表示求1到N有多少 ...

  2. LOJ# 572. 「LibreOJ Round #11」Misaka Network 与求和(min25筛,杜教筛,莫比乌斯反演)

    题意 求 \[ \sum_{i = 1}^{n} \sum_{i = 1}^{n} f(\gcd(i, j))^k \pmod {2^{32}} \] 其中 \(f(x)\) 为 \(x\) 的次大质 ...

  3. BZOJ-5244 最大真因数(min25筛)

    题意:一个数的真因数指不包括其本身的所有因数,给定L,R,求这个区间的所有数的最大真因数之和. 思路:min25筛可以求出所有最小因子为p的数的个数,有可以求出最小因子为p的所有数之和. 那么此题就是 ...

  4. loj#6235. 区间素数个数(min25筛)

    题意 题目链接 Sol min25筛的板子题,直接筛出\(g(N, \infty)\)即可 筛的时候有很多trick,比如只存\(\frac{N}{x}\)的值,第二维可以滚动数组滚动掉 #inclu ...

  5. 「学习笔记」Min25筛

    「学习笔记」Min25筛 前言 周指导今天模拟赛五分钟秒第一题,十分钟说第二题是 \(\text{Min25}​\) 筛板子题,要不是第三题出题人数据范围给错了,周指导十五分钟就 \(\text{AK ...

  6. [总结] min-25筛

    再不写总结我又会忘掉啊啊啊啊啊啊啊啊啊 这个\(min-25\)筛主要用来求一个积性函数的前缀和,就像这样\[\sum_{i=1}^n f(i)\] 不过这个积性函数要满足两个条件:质数\(p\)的函 ...

  7. min25筛学习总结

    前言 杜教筛学了,顺便把min25筛也学了吧= =刚好多校也有一道题需要补. 下面推荐几篇博客,我之后写一点自己的理解就是了. 传送门1 传送门2 传送门3 这几篇写得都还是挺好的,接下来我就写下自己 ...

  8. Min25筛

    Min25筛 我是沙雕... 从yyb博客蒯的 要求:\(\sum_{i=1}^nF(x)\) \(F(x)\)是积性函数. \(Min25\)筛能用的前提:质数处的\(f(p)\)值是关于\(p\) ...

  9. 莫比乌斯反演/线性筛/积性函数/杜教筛/min25筛 学习笔记

    最近重新系统地学了下这几个知识点,以前没发现他们的联系,这次总结一下. 莫比乌斯反演入门:https://blog.csdn.net/litble/article/details/72804050 线 ...

随机推荐

  1. 向pom.xml中配置Maven使用JDK8编译

    maven项目会用maven-compiler-plugin默认的jdk版本来进行编译,如果不指明版本就容易出现版本不匹配的问题,可能导致编译不通过的问题. 解决办法:在pom文件中配置maven-c ...

  2. openresty 学习笔记小结:综合应用实例

    openresty 学习笔记小结:综合应用实例 这个综合实验实现的功能其实很简单,用户访问一个页面,显示一个默认页面.输入参数(post或者get都可以),如果参数在数据库查询得到并满足一定条件,根据 ...

  3. Vue的常用特性

    Vue的常用特性 一.表单基本操作 都是通过v-model 单选框 1. 两个单选框需要同时通过v-model 双向绑定 一个值 2. 每一个单选框必须要有value属性 且value值不能一样 3. ...

  4. Activiti Exploer工作流控制台使用指南!使用Activiti Explorer定义部署执行工作流

    Activiti Explorer简介 Activiti Explorer: Activiti控制台,是一个web应用程序 从Activiti的官方网站下载Activiti的压缩zip文件时,Acti ...

  5. Spring如何使用三级缓存解决循环依赖

    Spring如何使用三级缓存解决循环依赖 首先来了解一下什么是循环依赖 @Component public class A { @Autowired B b; } @Component public ...

  6. SpringBoot——配置类实现WebMvcConfigurer接口来配置拦截器、view-controller、视图解析器等

    目的:为了保留SpringBoot对SpringMVC自动配置,另外我们还想要做一些自己拓展的功能 如何做扩展? 以配置view-controller实现跳转为例: 原先在SpringMvc中我们写v ...

  7. 二、Nginx 服务器升级

      1,编译新版本的nginx 软件 [root@client lnmp_soft]# tar -xf nginx-1.12.2.tar.gz -C .. [root@client lnmp_soft ...

  8. ES5中的类

    之前小编对于类和类的基本特征(所谓的封装.继承.多态)理解一直不是很到位,同时在实际项目应用中也用的比较少,今天小编就结合ES5中的基本用法和大家聊聊,希望小伙伴会在这篇文章有属于自己的收获,并能够在 ...

  9. 【VBA】显示所有隐藏的名称管理器中的名称

    Excel提示这个 代码: Sub DisplayNames() Dim Na As Name For Each Na In ThisWorkbook.Names Na.Visible = True ...

  10. Netty 面试题 (史上最全、持续更新)

    文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...