题目链接:循环之美

  这道题感觉非常优美……能有一个这么优美的题面和较高的思维难度真的不容易……

  为了表示方便,让我先讲一下两个符号。\([a]\)表示如果\(a\)为真,那么返回\(1\),否则返回\(0\); \(a \perp b\)表示\(a\)与\(b\)互质。

  首先,我们需要考虑一个分数要成为纯循环小数需要满足什么条件。

  我们先来回想一下,我们是怎样使用除法来判断一个分数$\frac{x}{y}$是否是纯循环小数的。显然我们是一路除下去,什么时候出现了相同的余数,那么这个数就是一个循环小数。如果第一个重复的余数是$x$,那么这个数就是纯循环小数。这种方法实际上就是存在一个数$l\neq 0$,使得:$$xk^l \equiv x (\bmod y)$$

  又由于题目要求值不重复,那么我们可以得到$x \perp y$。所以,我们可以推出$k^l \equiv 1(\bmod y)$。所以我们只需$k \perp y$即可。

  于是,我们实际上是要求这个式子:

\begin{aligned}&\sum_{x=1}^{n} \sum_{y=1}^{m}[x\perp y][y \perp k]\\=&\sum_{y=1}^{m}[y\perp k]\sum_{x=1}^{n}[x\perp y]\end{aligned}

  用一下莫比乌斯反演,可以得到:

\begin{aligned}&\sum_{y=1}^{m}[y\perp k] \sum_{x=1}^{n}\sum_{d|x,d|y}\mu(d)\\=&\sum_{y=1}^{m}[y\perp k]\sum_{d|y}^{n}\mu(d)\lfloor \frac{n}{d}\rfloor \end{aligned}

  再通过换一下枚举顺序,可得:

\begin{aligned}&\sum_{d=1}^{n}\mu(d)\lfloor \frac{n}{d} \rfloor \sum_{y=1}^{m}[d\ |\ y][y\perp k]\\=&\sum_{d=1}^{n}\mu(d)\lfloor \frac{n}{d}\rfloor \sum_{i=1}^{\lfloor \frac{m}{d} \rfloor}[id\perp k]\\=& \sum_{d=1}^{n}[d\perp k]\mu(d)\lfloor \frac{n}{d}\rfloor \sum_{i=1}^{\lfloor \frac{m}{d} \rfloor}[i\perp k]\end{aligned}

  最后一步用了互质的一个性质,那就是$[ab\perp c]=[a\perp c][b\perp c]$。这点应该很好理解吧。

  我们不妨设$f(n,k)=\sum_{i=1}^n[i\perp k]$,那么我们只要在$O(1)$的时间内求出$f$,复杂度就是$O(n)$,就可以得到$84$分。实际上,我们可以得到一个式子:

$$f(n,k)=\lfloor \frac{n}{k} \rfloor f(k,k)+f(n\bmod k,k)$$

  这个应该也不难理解,因为$[a\perp b]=[a\bmod b \perp b]$

  于是我们就可以对$f(n,k)$预处理出$n\le k$的值,每次求值就变成$O(1)$了。于是$84$分到手了。

  我们考虑接下来该如何优化。由于$\lfloor \frac{m}{x} \rfloor$只有$\sqrt{m}$种取值,$\lfloor \frac{n}{x} \rfloor$只有$\sqrt{n}$种取值,于是我们显然可以分段求和。然后,我们就需要快速求出$\sum_{i=1}^n[i\perp k]\mu(i)$的值。

  不妨设$g(n,k)=\sum_{i=1}^n[i\perp k]\mu(i)$,我们来考虑一下这个函数如何快速求。我们先考虑$k$的一个质因数$p$,那么$k$显然可以写成$p^cq$的形式。由于在$[1,n]$的范围中只有与$k$互质的才是有效值,那么若$x\perp k$,我们可以得到$x\perp p$并且$x\perp q$。于是,我们可以考虑从$x\perp q$的取值中减去$x$不与$p$互质的部分,就可以得到$x\perp k$的部分。这里如果不懂的话可以自己画一个$x\perp q$,$x\perp p$,$x\perp k$的关系图理解一下。

  由于所有与$q$互质的数一定可以写成$p^xy(y\perp q)$的形式。那么我们需要减去的数一定满足$x>0$。又由于当$x>1$时$\mu(p^xy)=0$,所以我们只需要考虑$x=1$的情况即可。在这种情况下,我们需要考虑的数就是$py(y\perp q)$的形式,所以我们可以得到如下式子:\begin{aligned}  g(n,k)&=\sum_{i=1}^n[i\perp q]\mu(i)-\sum_{y=1}^{\lfloor\frac{n}{p}\rfloor}[py\perp q]\mu(py) \\&=g(n,q)- \sum_{y=1}^{\lfloor\frac{n}{p}\rfloor}[y\perp q]\mu(py)\end{aligned}

  上面的最后一步是由于$p\perp q$,所以$py\perp q$只需在保证$y\perp q$即可。

  我们接着来考虑后一个式子。显然当$p\perp y$的时候$\mu(py)=\mu(p)\mu(y)$,否则$\mu(py)=0$。于是,我们又得到了:

\begin{aligned} g(n,k)&=g(n,q)- \sum_{y=1}^{\lfloor\frac{n}{p}\rfloor}[y\perp p][y\perp q]\mu(p)\mu(y)\\&=g(n,q)-\mu(p)\sum_{y=1}^{\lfloor\frac{n}{p}\rfloor}[y\perp k]\mu(y)\\&=g(n,q)+g(\lfloor\frac{n}{p}\rfloor,k) \end{aligned}

  于是我们就可以递归求解了。容易发现边界情况就是$n=0$或者$k=1$。$n=0$的时候直接返回$0$就可以了,$k=1$的时候就是莫比乌斯函数的前缀和,用杜教筛求出来就可以了。由于每次递归要么$n$会变成$\lfloor \frac{n}{p} \rfloor$,有$O(\sqrt{n})$种取值;要么$p$少了一个质因数,有$\omega(k)$种取值,所以总共有$O(\omega(k)\sqrt{n})$种取值,记忆化搜索即可。其中$\omega(k)$表示$k$的不同的质因子数目。于是最后的总复杂度为$O(\omega(k)\sqrt{n}+n^{\frac{2}{3}})$,可以通过此题。

  两个细节:

  可以在递归求$g$的时候不直接记$k$,而是记录$k$还剩下多少个质因数,方便存储;

  记忆化的时候可以开哈希链表存储,用$map$也可以,或者干脆分$n,m$以及小于、大于根号的情况存储也可以。

  第一次写这种题的题解,好像写得过于详细了(其实是因为我什么都不会),请大神们不要喷……

  下面贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 5000010
#define mod 100007
#define maxk 2010 using namespace std;
typedef long long llg; int n,m,k,pr_k[maxk],lp;
int s[maxn],ls,f[maxk];
int head[mod],next[maxn],to[maxn],tt;
int h1[11][mod],n1[maxn],t1[maxn],t2;
bool vis[maxn],huzhi[maxk];
llg ans,zto[maxn],zt1[maxn],mu[maxn]; int gcd(int a,int b){
int r=a%b;
while(r) a=b,b=r,r=a%b;
return b;
} void pre(){
mu[1]=1;
for(int i=2;i<maxn;i++){
if(!vis[i]) s[++ls]=i,mu[i]=-1;
for(int j=1;j<=ls && s[j]*i<maxn;j++){
vis[s[j]*i]=1;
if(i%s[j]) mu[i*s[j]]=-mu[i];
else{mu[i*s[j]]=0;break;}
}
}
for(int i=2;i<maxn;i++) mu[i]+=mu[i-1];
for(int i=1;i<=k;i++){
huzhi[i]=(gcd(i,k)==1);
f[i]=f[i-1]+huzhi[i];
}
} llg suan(int x){return (x/k)*f[k]+f[x%k];}
llg solveu(int x){
if(x<maxn) return mu[x];
for(int i=head[x%mod];i;i=next[i]) if(to[i]==x) return zto[i];
int now=++tt; to[tt]=x;next[tt]=head[x%mod];head[x%mod]=tt; zto[now]=1;
for(int i=2,nt=0;nt<x;i=nt+1) nt=x/(x/i),zto[now]-=(nt-i+1)*solveu(x/i);
return zto[now];
} llg g(int x,int y){
if(!x) return solveu(y);
if(y<=1) return y;
for(int i=h1[x][y%mod];i;i=n1[i]) if(t1[i]==y) return zt1[i];
int now=++t2; t1[t2]=y;n1[t2]=h1[x][y%mod];h1[x][y%mod]=t2;
return zt1[now]=g(x-1,y)+g(x,y/pr_k[x]);
} int main(){
File("a");
scanf("%d %d %d",&n,&m,&k);
pre();
for(int i=1;s[i]<=k;i++) if(k%s[i]==0) pr_k[++lp]=s[i];
for(int d=1,l=min(n,m),nt;d<=l;d=nt+1){
nt=min(n/(n/d),m/(m/d));
ans+=(g(lp,nt)-g(lp,d-1))*(llg)(n/d)*suan(m/d);
}
printf("%lld",ans);
return 0;
}

   最后附一个BZOJ的提交网址:BZOJ 4652 循环之美

UOJ #221 【NOI2016】 循环之美的更多相关文章

  1. [UOJ#221][BZOJ4652][Noi2016]循环之美

    [UOJ#221][BZOJ4652][Noi2016]循环之美 试题描述 牛牛是一个热爱算法设计的高中生.在他设计的算法中,常常会使用带小数的数进行计算.牛牛认为,如果在 k 进制下,一个数的小数部 ...

  2. luogu 1587 [NOI2016]循环之美

    LINK:NOI2016循环之美 这道题是 给出n m k 求出\(1\leq i\leq n,1\leq j\leq m\) \(\frac{i}{j}\)在k进制下是一个纯循环的. 由于数值相同的 ...

  3. bzoj4652 [Noi2016]循环之美

    Description 牛牛是一个热爱算法设计的高中生.在他设计的算法中,常常会使用带小数的数进行计算.牛牛认为,如果在k进制下,一个数的小数部分是纯循环的,那么它就是美的.现在,牛牛想知道:对于已知 ...

  4. [NOI2016]循环之美

    Description 牛牛是一个热爱算法设计的高中生.在他设计的算法中,常常会使用带小数的数进行计算.牛牛认为,如果在 k  进制下,一个数的小数部分是纯循环的,那么它就是美的.现在,牛牛想知道:对 ...

  5. BZOJ4652: [Noi2016]循环之美(莫比乌斯反演,杜教筛)

    Description 牛牛是一个热爱算法设计的高中生.在他设计的算法中,常常会使用带小数的数进行计算.牛牛认为,如果在 k  进制下,一个数的小数部分是纯循环的,那么它就是美的.现在,牛牛想知道:对 ...

  6. BZOJ4652 [Noi2016]循环之美 【数论 + 莫比乌斯反演 + 杜教筛】

    题目链接 BZOJ 题解 orz 此题太优美了 我们令\(\frac{x}{y}\)为最简分数,则\(x \perp y\)即,\(gcd(x,y) = 1\) 先不管\(k\)进制,我们知道\(10 ...

  7. luogu P1587 [NOI2016]循环之美

    传送门 首先要知道什么样的数才是"纯循环数".打表可以发现,这样的数当且仅当分母和\(k\)互质,这是因为,首先考虑除法过程,每次先给当前余数\(*k\),然后对分母做带余除法,那 ...

  8. 题解 P1587 【[NOI2016]循环之美】

    知识点:莫比乌斯反演 积性函数 杜教筛 废话前言: 我是古明地恋,写这篇题解的人已经被我 请各位读者自行无视搞事的恋恋带有删除线的内容,谢谢茄子. 这道题目本身并不难,但是公式推导/代码过程中具有迷惑 ...

  9. BZOJ4652 NOI2016循环之美(莫比乌斯反演+杜教筛)

    因为要求数值不同,不妨设gcd(x,y)=1.由提示可以知道,x/y是纯循环小数的充要条件是x·klen=x(mod y).因为x和y互质,两边同除x,得klen=1(mod y).那么当且仅当k和y ...

  10. [NOI2016]循环之美(杜教筛)

    首先要求每个数互不相等,故有$x\perp y$. 可以发现$\frac{x}{y}$在$k$进制下为纯循环小数的充要条件为$x\cdot k^{len}\equiv x(mod\ y)$,即$y\p ...

随机推荐

  1. linux内核调试技术之printk

    原创博客:欢迎转载,转载请注明出处https://i.cnblogs.com/EditPosts.aspx?postid=6218383 1.简介(基于s3c2440 linux) 在内核调试技术之中 ...

  2. 1000行代码实现MVVM (类似Angular1.x.x , Vue)

    最近花了近半个多月的时间, 自己纯手工写了一个很小型的类angularjs/vue的mvvm 库. 目前已经用于公司一个项目. 项目托管在github https://github.com/leonw ...

  3. TypeScript 强类型 JavaScript – Rafy Web 框架选型

    今天看到了 AngularJs 2.0 版本将基于 TypeScript 构建 的消息.与同事们对 TypeScript 展开了讨论.本文记录一些个人的想法. 理想的 JavaScript 开发模式 ...

  4. Scala快速概览

    IDEA工具安装及scala基本操作 目录 一. 1. 2. 3. 4. 二. 1. 2. 3. 三. 1. 2. 3. 4. 5. 6. 7. 四. 1. (1) (2) (3) (4) (5) ( ...

  5. 几道web前端练习题目

    在 HTML 语言中,以下哪个属性不是通用属性?A]<class>B]<title>C]<href>D]<style> 在线练习:http://hove ...

  6. Asp.Net MVC 从数据库生成代码(包括页面)

    项目需要,数据库已经设计完成,需要生成相关的数据访问代码和页面. 参考:http://www.tracefact.net/asp-net/aspnetmvc-model-part1.aspx http ...

  7. 初识Git

    Git是目前世界上最先进的分布式版本控制系统.在Git诞生之前,我们一直使用的是集中式版本控制系统(如CVS.SVN等),那么两者有什么不同呢?分布式的优势又在哪里呢? 分布式vs集中式 集中式版本控 ...

  8. 这个图片切换动画只用CSS3实现

    体验效果:http://hovertree.com/texiao/css3/39/ 这是一个使用纯CSS3实现的图文切换效果,没使用js脚本.点击左右箭头或者索圆点引按钮可以切换内容. 本特效中使用到 ...

  9. 大朋展翅 html5上传图片(三)一解决部分手机拍相册批量上传图片转向问题

    在经过前面的改进之后本来以为已经没有问题了,但经过我们神通广大的测试的测试,发现相册中的图片在上传时也会发生转向问题.既然前面都解决了拍照转向的问题,那么相册中图片的上传也容易解决.修改一下需要旋转图 ...

  10. Bootstrap之导航条

    基本导航条 <!-- navbar-inverse相反颜色风格 --> <!-- navbar-static-top去除圆角 --> <!-- navbar-fixed- ...