题解 [NOI2016]循环之美
题意描述
给定 \(n,m,k\),求 \(k\) 进制下值不同的 \(\frac{x}{y}\) 且 \(\frac{x}{y}\) 为纯循环小数的个数
\(n,m\le 10^9,2\le k\le 2\times 10^3,1\le x\le n,1\le y\le m\)
首先要知道一点:当 \([x\perp y\land y\perp k]\) 时 \(\frac{x}{y}\) 产生一次贡献
因此答案为:\(\sum\limits_{x=1}^n\sum\limits_{y=1}^m\epsilon([x\perp y])\epsilon([y\perp k])\)
然后推式子
\[\begin{aligned}
\sum\limits_{x=1}^n\sum\limits_{y=1}^m\epsilon([x\perp y])\epsilon([y\perp k])&=\sum\limits_{y=1}^m\epsilon([y\perp k])\sum\limits_{x=1}^n\epsilon([x\perp y])\\
&=\sum\limits_{y=1}^m\epsilon([y\perp k])\sum\limits_{x=1}^n\sum\limits_{d\mid x,d\mid y}\mu(d)\\
&=\sum\limits_{d=1}^n\mu(d)\lfloor\frac{n}{d}\rfloor\sum\limits_{y=1}^{m}\epsilon([d\perp y])\epsilon([y\perp k])\\
&=\sum\limits_{d=1}^n\epsilon([d\perp k])\mu(d)\lfloor\frac{n}{d}\rfloor\sum\limits_{y=1}^{\lfloor\frac{m}{d}\rfloor}\epsilon([j\perp k])
\end{aligned}
\]
于是我们只需要求
\[\begin{array}{lr}
f(x)=\sum\limits_{i=1}^x\epsilon([i\perp k])\mu(i)\\
g(x)=\sum\limits_{i=1}^x\epsilon([i\perp k])\\
h(x)=\lfloor\frac{n}{x}\rfloor
\end{array}
\]
三个函数即可快速得到答案
第一个:
\(\epsilon\) 可是完全积性函数诶~
于是杜教筛就完了
当然这样写起来很麻烦,我们换种做法
\[\begin{aligned}
f(x,k)&=\sum\limits_{i=1}^x\mu(i)\epsilon([i\perp k])\\
&=\sum\limits_{i=1}^x\mu(i)\sum\limits_{d\mid i,d\mid k}\mu(d)\\
&=\sum\limits_{d\mid k}\mu(d)\sum\limits_{i=1}^{\lfloor\frac{x}{d}\rfloor}\mu(i\times d)
\end{aligned}
\]
\(\because i\not\perp d\ 时\ \mu(i\times d)\ 无贡献\)
\(\therefore\)
\[\begin{aligned}
f(x,k)&=\sum\limits_{d\mid k}\mu(d)\sum\limits_{i=1,i\perp d}^{\lfloor\frac{x}{d}\rfloor}\mu(i)\mu(d)\\
&=\sum\limits_{d\mid k}\mu^2(d)\sum\limits_{i=1,i\perp d}^{\lfloor\frac{x}{d}\rfloor}\mu(i)\\
&=\sum\limits_{d\mid k}\mu^2(d)\sum\limits_{i=1}^{\lfloor\frac{x}{d}\rfloor}\epsilon([i\perp d])\mu(i)\\
&=\sum\limits_{d\mid k}\mu^2(d)f(\lfloor x/d\rfloor,d)
\end{aligned}\]
于是就成了一个递归……
当 \(f(x,k=1)\) 时用杜教筛
第二个:
若 \(a\perp k\),则\(a+n\times k\perp k\)
因此有:
\[g(x)=\lfloor\frac{x}{k}\rfloor g(k)+g(x\%k)
\]
\(O(k)\) 预处理即可
第三个:滑稽吧这是个人都会……
点击查看代码
#include<bits/stdc++.h>
//#pragma GCC optimize(2,3,"Ofast")
#define int long long
#define inf 1e18
#define N 2005
#define M 1000005
#define ls k<<1
#define rs k<<1|1
#define mid ((l+r)>>1)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define pii pair<int,int>
#define il inline
#define Sqrt(x) for(int l=1,r;l<=x;l=r+1)
#define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
il int read(){
int w=0,h=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')h=-h;ch=getchar();}
while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
return w*h;
}
int n,m,K,g[N];
int prime[M],mu[M],sum[M],cnt;
bool vis[M];
map<pii,int>dp;
int gcd(int a,int b){return(!b)?a:gcd(b,a%b);}
void Euler(){
vis[1]=true;mu[1]=1;
for(int i=2;i<M;i++){
if(vis[i]==false)prime[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&i*prime[j]<M;j++){
vis[i*prime[j]]=true;
if(i%prime[j]==0)break;
mu[i*prime[j]]=-mu[i];
}
}
for(int i=1;i<=K;i++)g[i]+=g[i-1]+(gcd(i,K)==1);
for(int i=1;i<M;i++)sum[i]+=sum[i-1]+mu[i];
}
int G(int x){return x/K*g[K]+g[x%K];}
int Calc(int x,int k){
if(x==0)return 0;
if(k==1&&x<M)return sum[x];
if(dp[mp(x,k)])return dp[mp(x,k)];
int res=0;
if(k==1){
Sqrt(x)l+=(l==1),r=x/(x/l),res-=Calc(x/l,1)*(r-l+1);
return dp[mp(x,k)]=res+1;
}
for(int d=1;d*d<=k;d++)
if(k%d==0){
if(mu[d])res+=Calc(x/d,d);
if(mu[k/d]&&d*d<k)res+=Calc(x/(k/d),k/d);
}
return dp[mp(x,k)]=res;
}
signed main(){
n=read();m=read();K=read();Euler();
int res=0,cur,lst=0;
Sqrt(min(n,m)){
r=min(n/(n/l),m/(m/l));
cur=Calc(r,K);
res+=(cur-lst)*G(m/l)*(n/l);
lst=cur;
}
printf("%lld\n",res);
return 0;
}