bzoj 2820: YY的GCD
Posted 日拱一卒 功不唐捐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2820: YY的GCD相关的知识,希望对你有一定的参考价值。
2820: YY的GCD
Time Limit: 10 Sec Memory Limit: 512 MBDescription
Input
Output
Sample Input
10 10
100 100
Sample Output
2791
HINT
T = 10000
N, M <= 10000000
先推一个:
n m
Σ Σ gcd(x,y)=p
x y
n/p m/p
= Σ Σ Σ gcd(x’,y’)=1
p x\' y’
n/p m/p
= Σ Σ Σ e(gcd(x’,y’))
p x’ y’
n/p m/p
= Σ Σ Σ Σ μ(d)
p x’ y’ d\\gcd(x’,y’)
n/pd m/pd
= Σ Σ Σ Σ μ(d)
p d x’’ y’’
n/t m/t
= Σ Σ Σ Σ μ(d) 令p*d=t
t p\\t x’’ y’’
= Σ Σ μ(d) floor(n/t) floor(m/t)
t p\\t
∴ans=Σ Σ μ(T/p) floor(n/T)floor(m/T)
T p\\T
现在是枚举T、P,肯定TLE
所以继续推
令 f(T)=Σ μ(T/p) p为素数
p\\T
根据线性筛的思路
当T为素数时 只有p=T,∴f(T)=μ(1)=1
当T不为素数时,
令T=i*prime[j]
对i分解质因数,i=p1^k1*p2^k2*p3^k3……
当i%prime[j]!=0时, f[i]=Σ μ(i/p)=μ(p1^(k1-1)*p2^k*p3^k……)+μ(p1^k1*p2^(k2-1)*p3^k3……)+μ(p1^k1*p2^k2*p3^(k3-1)……)+……
p\\i
为了方便表示,令s1=μ(p1^(k1-1)*p2^k*p3^k……) s2=μ(p1^k1*p2^(k2-1)*p3^k3……) s3=μ(p1^k1*p2^k2*p3^(k3-1)……) ……
f[T]=Σ μ(T/p)=μ(s1*prime[j])+μ(s2*prime[j])+μ(s3*prime[j])+……+μ(T/prime[j])
p\\T
= μ(prime[j])*(μ(s1)+μ(s2)+μ(s3)+……)+μ(T/prime[j])
=μ(prime[j])*f(i)+μ(i)
=-f(i)+μ(i)
当i%prime[j]==0时,i分解质因数,其中必有一个pi=prime[j]
∴上面f(T)中每一项中,除最后一项外,前面每一项的prime[j]都可以与si中的1个pi合并为一个,即出现了pi^ki ki>=2
∴f(T)除最后一项都=0
看最后一项,μ(T/prime[j]),因为T=i*prime[j],所以prime[j]约去
所以最优后一项=μ(i)
综上所述,线性筛时,枚举i
当i为素数时 f(i)=1
当i%prime[j]!=0时,f(i*prime[j])= μ(i)-f(i)
当i%prime[j] =0时, f(i*prime[j])=μ(i)
为什么这里把T是素数换成了i是素数
因为线性筛的过程,T若是素数,一定可以在某个i时被枚举到
然后i*prime[j]就相当于推导过程中的T
#include<cstdio> #include<algorithm> #define N 10000001 using namespace std; int t; long long x,y; int prime[N],miu[N],cnt,f[N],sum[N]; bool v[N]; void pre() { miu[1]=1; for(int i=2;i<N;i++) { if(!v[i]) { v[i]=true; prime[++cnt]=i; miu[i]=-1; f[i]=1; } for(int j=1;j<=cnt;j++) { if(i*prime[j]>N-1) break; v[i*prime[j]]=true; if(i%prime[j]==0) { miu[i*prime[j]]=0; f[i*prime[j]]=miu[i]; break; } miu[i*prime[j]]=-miu[i]; f[i*prime[j]]=miu[i]-f[i]; } } for(int i=1;i<N;i++) sum[i]=sum[i-1]+f[i]; } void solve() { long long k=min(x,y),j,ans=0; for(long long i=1;i<=k;i=j+1) { j=min(x/(x/i),y/(y/i)); ans+=(x/i)*(y/i)*(sum[j]-sum[i-1]); } printf("%lld\\n",ans); } int main() { pre(); scanf("%d",&t); while(t--) { scanf("%lld%lld",&x,&y); solve(); } }
元元真厉害\\(^o^)/~
我的智商啊~~~~(>_<)~~~~
以上是关于bzoj 2820: YY的GCD的主要内容,如果未能解决你的问题,请参考以下文章