Luogu P2257 YY的GCD
数论太难了吧...
给定 \(n\),\(m\),\(T\),\(T\) 为数据组数,求:
\(n,m\le 1\times 10^7\),\(T=10^4\)
首先推推式子吧:
因为
所以有
替换,得到
枚举 \(d\)
设 \(T=pd\),枚举 \(T\)
这样前面就是一个整除分块,复杂度是 \(\operatorname{O}(T\sqrt n)\):
while(T--){
n=read(),m=read();
if(n>m) swap(n,m);
int l=1,r;
ll ans=0;
for(l=1;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=(ll)(n/l)*(ll)(m/l)*(ll)(F[r]-F[l-1]);
}
printf("%lld\n",ans);
}
设:
于是我们要求的就是 \(F\) ,怎么求呢?
solution 1
这不就是 \(F=\mu *f\) 吗,直接大力卷积!
(\(\mu\) 线性筛就好了):
FOR(i,1,N){
FOR(j,1,N){
if(i*j>N) break;
F[i*j]+=mu[i]*f[j];
}
}
每一个 \(i\) 只会被算 \(\lfloor\frac{n}{i}\rfloor\) 次,\(\sum\frac{n}{i}=n\sum\frac{1}{i}\),是个调和级数,差不多 \(\operatorname{O}(n\ln n)\),能过,但是要吸氧。
另:
根据 \(\mu\) 函数的定义,我们可以得出以下的代码:
FOR(i,1,N)
for(int j=i*2;j<=N;j+=i)
f[j]-=f[i];
这样新的 \(f\) 就是我们要求的 \(F\) 了,但是我不会证,一样是 \(\operatorname{O}(n\ln n)\)。
这种方法不用线性筛,会比上面的稍快一点
solution 2
对于这一坨东西,我们其实可以用类似埃氏筛的办法解决,这样要快许多。
具体地,可以观察到只有 \(p\) 为质数时才会累加,那么就枚举质数,对它的倍数进行累加即可:
FOR(i,1,cnt)
for(int j=1;j*p[i]<=N;j++)
f[j*p[i]]+=mu[j];
复杂度约为 \(\operatorname{O}(n\ln\ln n)\),不用吸氧了。
solution 3
抛开以上所有式子,重新来看这个题:
如果我们能够构造一个
那么就
所以重点是如何构造 \(F\)。
设
那么我们想构造的 \(F\) 就有
所以
回到 solution 1,就做完了。所以只是换了个角度思考,实质还是没有区别啊!
至此,解法已经有好多了,可以通过此题。但是
太慢了!我们需要线性求 F!
所以:
solution 4
还是回到那个式子:
我们不妨改写成前一步的样子:
好像可以线性筛出来啊!
先看看这个 \(F(T)\) 是不是积性的。
\(F=\mu *f\),所以 \(F(1)\dots\),没有质数能整除 \(1\) 啊,那 \(F(1)=0\)?那就不是积性函数呗。我一直以为只有积性函数可以用欧拉筛,这下看起来不是积性函数也能筛,满足条件就行了呗。
-
我们假设 \(T=i\times k\),\(k\) 是 \(T\) 的最小质因子。(以下自动忽略非素数的 \(p\))
-
① 如果 \(T\in \operatorname{prime}\),那么 \(F(T)=\mu(1)=1\)
-
② \(i\bmod k=0\),也就是说 \(T\) 存在多个最小质因子
- 若 \(\mu(i)\neq0\),则当且仅当 \(p=k\) 时,\(\mu(\frac{T}{p})=\mu(i)\neq0\),其余情况 \(\mu(\frac{T}{p})\) 因为多个质因子 \(k\) 的存在都等于 \(0\),所以 \(F(T)=\mu(i)\)
- 若 \(\mu(i)=0\),则 \(p\neq k\) 时,\(\mu(\frac{T}{p})=0\);\(p=k\) 时,\(\mu(\frac{T}{p})=\mu(i)=0\)。所以 \(F(T)=\mu(i)\)
综上 \(i\bmod k=0\) 时,\(F(T)=\mu(i)\)
-
③ \(i\bmod k\ne0\)
我们在做线性筛的时候,是从 \(i\) 推到 \(T\) 的,观察:
那也就是说,\(T\) 比 \(i\) 多了一个质因子 \(k\),则 \(F(T)\) 比 \(F(i)\) 多了一个 \(\mu(\frac{i\times k}{p(p=k)})=\mu(i)\)
观察第三个式子,所有 \(\mu\) 又都要取反,最终得到了:
由此我们写出线性筛总式(姑且这么叫吧)就是:
\(F(T)=\begin{cases}F(T)=1&T\in \operatorname{prime}\\F(T)=\mu(i)&i\bmod k=0\\F(T)=-F(i)+\mu(i)&i\bmod k\neq 0\end{cases}\)
所以求 \(F\) 的复杂度是 \(\operatorname{O}(n)\) 的。
愉快的代码时间~
void init(){
bitset<N>isp;
isp.set();
isp[1]=0;
mu[1]=1;
FOR(i,2,N){
if(isp[i]) p[++cnt]=i,mu[i]=-1,F[i]=1;
for(int j=1;i*p[j]<=N&&j<=cnt;j++){
isp[i*p[j]]=0;
if(i%p[j]==0){
mu[i*p[j]]=0;
F[i*p[j]]=mu[i];
break;
}
F[i*p[j]]=-F[i]+mu[i];
mu[i*p[j]]=-mu[i];
}
}
FOR(i,1,N) F[i]+=F[i-1];
}
至此,本题得到了完美解决 大概
(以上内容整理自题解)

浙公网安备 33010602011771号