洛谷P3327 笔记
题意
设 为 的因数个数,然后给定 组询问,对于每一个询问给定 和 ,求 。
正文
重要结论
这题的难点之一就是第一步的转换。
需要用到一个重要结论:
来自这位dalao的证明:
考虑从朴素的角度求出 ,一种可行的方法是枚举每种质因子的出现次数。
于是对于 的一种质因子 ,设 表示 中有 个 ,则这种暴力的策略会枚举 的 种不同的大小 。于是得出结论:对于 , 会被枚举 次。
那么对于 ,只要让质因子被枚举 次即可。那么一种可行的策略就是枚举所有满足 的数对,这样的话当 时, ,此时 被枚举 次。反之亦然。于是 共被枚举 次,满足条件。所以结论成立。
推柿子
于是原式变为
这个 非常的臭,用莫比乌斯函数把它撅了。
于是转换成:
枚举 。就有
进一步地,枚举 。于是
这个时候思路已经逐渐出来了。后面的 和 是标准的整除分块模板。设 ,原式又变成了 。
由于 珂以线性筛预处理,于是就出现了整除分块套整除分块,非常鬼畜!但正解就是这样。
code
//writer:Oier_szc #include <bits/stdc++.h> #define TS cerr<<"I AK IOI"<<endl; #define int long long using namespace std; const int N=5e4+5,INF=2e9,mod=1e9+7; int t; int n,m; int primes[N],st[N],len=0; int f[N],g[N]; void init() { f[1]=1; for(int i=2;i<=5e4;++i) { if(!st[i]) primes[++len]=i,f[i]=-1; for(int j=1;j<=len&&primes[j]<=5e4/i;++j) { st[i*primes[j]]=true; if(i%primes[j]==0) { f[i*primes[j]]=0; break; } else f[i*primes[j]]=-f[i]; } } for(int i=1;i<=5e4;++i) { f[i]+=f[i-1]; for(int l=1,r;l<=i;l=r+1) { r=i/(i/l); g[i]+=(r-l+1)*(i/l); } } } signed main() { init(); scanf("%lld",&t); while(t--) { scanf("%lld%lld",&n,&m); int R=min(n,m),ans=0; for(int l=1,r;l<=R;l=r+1) { r=min(n/(n/l),m/(m/l)); ans+=(f[r]-f[l-1])*g[n/l]*g[m/l]; } printf("%lld\n",ans); } return 0; }
本文作者:StevenZC
本文链接:https://www.cnblogs.com/StevenZC/p/18012280
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步