【题解】LOJ #2085 / 洛谷 P1587「NOI2016」循环之美【莫比乌斯反演】

题目链接

题目链接

题意

(k) 进制下,分子为 ([1,n]),分母为 ([1,m]) 的纯循环小数有多少个(值相同算同一个)。(n,mleq 10^9)(kleq 2000)

题解

根据我们小学二年级就学过的结论,对于 (k) 进制下的最简分数 (dfrac{x}{y}) 是纯循环小数,当且仅当 (yot k)。于是问题变为:

[egin{aligned} &sum_{i=1}^{n}sum_{j=1}^{n}[iot j][jot k]\ =&sum_{j=1}^{m}[jot k]sum_{j=1}^{n}[iot j]\ =&sum_{j=1}^{m}[jot k]sum_{j=1}^{n}sum_{d|gcd(i,j)}mu d\ =&sum_{d=1}^{n}[dot k]mu(d)sum_{j=1}^{m /d}sum_{i=1}^{n /d}[jot k]\ =&sum_{d=1}^{n}[dot k]mu(d)lfloor dfrac{n}{d} floorsum_{j=1}^{m /d}[jot k] end{aligned} ]

  • [f(x)=sum_{i=1}^x[iot k] ]

    • 由于 ([iot k])(f) 个一循环的,预处理 (f(1..k)) 后容易计算。
  • [g(x,k)=sum_{i=1}^x[iot k]mu(i) ]

[egin{aligned} g(x,k)=&sum_{i=1}^x[iot k]mu(i)\ =&sum_{i=1}^xmu(i)sum_{i|d}mu(i)\ =&sum_{d|k}^{x}mu(d)sum_{i|d}mu(i)\ =sum_{d|k}^{x}mu(d)sum_{p=1}^{x /d}mu(pd) end{aligned} ]

(p ot ot d)(mu(pd)=0)。我们继续:

[egin{aligned} g(x,k)=&sum_{d|k}^{x}mu^2(d)sum_{p=1}^{x /d}[pot d]\ =&sum_{d|k}^{x}[mu(d) eq 0]sum_{p=1}^{x /d}mu(p)[pot d]\ =&sum_{d|k}^{x}[mu(d) eq 0]g(lfloor dfrac{n}{d} floor,d) end{aligned} ]

递归计算,(g(n,1))(mu) 的前缀和。

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
int getint(){
	int ans=0,f=1;
	char c=getchar();
	while(c>'9'||c<'0'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		ans=ans*10+c-'0';
		c=getchar();
	}
	return ans*f;
}
#define ll long long
const int M=2e6,N=1e9;
int pri[M+1],mu[M+1],cnt=0;
bool vis[M+1],v[M];
unordered_map<int,int> mu2;
int n,m,k;
int f_[M];

int gcd(int x,int y){ return x?gcd(y%x,x):y; }
int f(int x){
    return f_[k]*(x/k)+f_[x%k];
}
int get_mu(int x){
	//f=mu,g=I,f*g=e
	if(x<=M)return mu[x];
	if(mu2.count(x))return mu2[x];
	ll ans=bool(x);
	for(int i=2,j;j<x&&i<=x;i=j+1){
		j=x/(x/i);
		ans-=(j+1ll-i)*get_mu(x/i);
	}
    return mu2[x]=ans;
}
ll g(int x,int k){
    if(k==1)return get_mu(x);
    if(!x)return 0;
    ll ans=0;
    for(int i=1;i*i<=k;i++){
        if(k%i)continue;
        if(x>=i&&mu[i]-mu[i-1])ans=ans+g(x/i,i);
        if(x>=k/i&&(mu[k/i]-mu[k/i-1])&&i*i!=k)ans=ans+g(x/(k/i),k/i);
    }
    return ans;
}

int main(){
    mu[1]=1;
    for(int i=2;i<=M;i++){
        if(!vis[i])pri[cnt++]=i,mu[i]=-1;
        for(int j=0;j<cnt&&i*pri[j]<=M;j++){
            vis[i*pri[j]]=1;
            if(i%pri[j])mu[i*pri[j]]=-mu[i];           
            else break;
        }
        mu[i]+=mu[i-1];
    }
    n=getint(),m=getint(),k=getint();
    for(int i=1;i<=k;i++)f_[i]=f_[i-1]+(gcd(i,k)==1);
    ll ans=0;
    for(ll l=1,r,sl=0;l<=min(n,m);l=r+1){
        r=min(n/(n/l),m/(m/l));
        int p=n/l,q=m/l;
        ll sr=g(r,k);
        ans+=(sr-sl)*p*f(q);
        sl=sr;
    }
    cout<<ans<<endl;
	return 0;
}

知识共享许可协议
若文章内无特别说明,公开文章采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
原文地址:https://www.cnblogs.com/wallbreaker5th/p/14187660.html