bzoj 4562 [NOI2016]循环之美 莫比乌斯反演

    xiaoxiao2021-03-25  157

    几年没写题解来更一篇。 首先有一个规律就是如果满足条件那么 gcd(y,k)=1 那么答案就是 i=1nj=1m[gcd(i,j)=1][gcd(j,k)=1] =j=1m[gcd(j,k)=1]i=1nt|i,t|jμ(t) =t=1mμ(t)ntj=1mt[gcd(tj,k)=1] ==t=1mμ(t)nt[gcd(t,k)=1]j=1mt[gcd(j,k)=1] O(n) 枚举 nt,mt 对于每段 j=1x[gcd(j,k)=1]=r|kμ(r)xr 直接算就行了。 设k的质因数分解为 pa11pa22....pacntcnt ki=pa11pa22....paii f(i,x)=t=1xμ(t)[gcd(t,ki)=1] 那么要求的是 f(cnt,x) f(i,x)=t=1xμ(t)[gcd(t,ki)=1] =t=1xμ(t)[gcd(t,ki1paii)=1] =t=1xμ(t)[gcd(t,ki1)=1][gcd(t,pi)=1] =t=1xμ(t)[gcd(t,ki1)=1]pi|tμ(t)[gcd(t,ki1)=1] =t=1xμ(t)[gcd(t,ki1)=1]t=1xpiμ(tpi)[gcd(tpi,ki1)=1] =t=1xμ(t)[gcd(t,ki1)=1]t=1xpiμ(tpi)[gcd(t,ki)=1] 然后第二段中如果 t%pi=0 没有贡献,否则当 gcd(t,pi)=1 μ(tpi)=μ(t) 因此上式 =t=1xμ(t)[gcd(t,ki1)=1]+t=1xpiμ(t)[gcd(t,ki)=1] =f(i1,x)+f(i,xpi) i=0 f(i,x) 可以通过杜教筛计算。 然后这个杜教筛就是把 i=1nxμ(i) 算一遍。 因此复杂度大概是 O(min(n,m)(k+logn)+n23logn)

    Orz 小火车

    #include <bits/stdc++.h> using namespace std; #define N 5100000 #define A 5000000 #define ll long long ll ans; int n,m,K,cnt,cnt1; int mu[N],prime[N],ip[N],sum[N],p[11],p1[110]; map<pair<int,int>,int>ma1; map<int,int>ma2; void init() { mu[1]=1; for(int i=2;i<=A;i++) { if(!ip[i]){prime[++cnt]=i;mu[i]=-1;} for(int j=1;j<=cnt&&i*prime[j]<=A;j++) { ip[i*prime[j]]=1; if(i%prime[j]==0)break; mu[i*prime[j]]=-mu[i]; } } for(int i=1;i<=A;i++) sum[i]=sum[i-1]+mu[i]; cnt=0; for(int i=1;i<=K;i++) if(K%i==0)p1[++cnt1]=i; for(int i=1;prime[i]<=K;i++) if(K%prime[i]==0)p[++cnt]=prime[i]; } int djs(int x) { if(x<=A)return sum[x]; if(ma2.count(x))return ma2[x]; int ret=1; for(int i=2,last;i<=x;i=last+1) { last=x/(x/i); ret-=djs(x/i)*(last-i+1); } return ma2[x]=ret; } int cal1(int x,int y) { if(y==0)return 0; if(x==0)return djs(y); pair<int,int> t=make_pair(x,y); if(ma1.count(t))return ma1[t]; int ret=cal1(x-1,y)+cal1(x,y/p[x]); return ma1[t]=ret; } int cal2(int x) { int ret=0; for(int i=1;i<=cnt1;i++) ret+=mu[p1[i]]*(x/p1[i]); return ret; } int main() { scanf("%d%d%d",&n,&m,&K); init(); for(int i=1,last;i<=m&&i<=n;i=last+1) { last=min(n/(n/i),m/(m/i)); ans+=(ll)(cal1(cnt,last)-cal1(cnt,i-1))*(n/i)*cal2(m/i); } printf("%lld\n",ans); return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-5338.html

    最新回复(0)