题解 [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;
}
posted @ 2022-07-20 20:57  pidan007  阅读(37)  评论(0编辑  收藏  举报