P1587 [NOI2016]循环之美

题目描述

牛牛是一个热爱算法设计的高中生。在他设计的算法中,常常会使用带小数的数进行计算。牛牛认为,如果在 $k$ 进制下,一个数的小数部分是纯循环的,那么它就是美的。现在,牛牛想知道:对于已知的十进制数 $n$ 和 $m$,在 $k$ 进制下,有多少个数值上互不相等的纯循环小数,可以用分数 $\frac xy$ 表示,其中 $1≤x≤n,1≤y≤m$,且 $x,y$是整数。一个数是纯循环的,当且仅当其可以写成以下形式:

$a.\dot{c_1} c_2 c_3 \dots c_{p - 1} \dot{c_p}$

其中,$a$ 是一个整数,$p≥1$;对于 $1≤i≤p$,$c_i$ 是 $k$ 进制下的一位数字。

例如,在十进制下,$0.45454545……=0.\dot {4} \dot {5}$是纯循环的,它可以用 $\frac {5}{11}$、$\frac{10}{22}$ 等分数表示;在十进制下,$0.1666666……=0.1\dot6$则不是纯循环的,它可以用 $1/6$ 等分数表示。需要特别注意的是,我们认为一个整数是纯循环的,因为它的小数部分可以表示成 $0$ 的循环或是 $k-1$ 的循环;而一个小数部分非 $0$ 的有限小数不是纯循环的。

输入输出格式

输入格式:

只有一行,包含三个十进制数N,M,K意义如题所述,保证 1≤n≤10^9,1≤m≤10^9,2≤k≤2000

输出格式:

一行一个整数,表示满足条件的美的数的个数。

输入输出样例

输入样例#1:
复制

2 6 10
输出样例#1:
复制

4

说明

满足条件的数分别是:

1/1=1.0000……
1/3=0.3333……
2/1=2.0000……
2/3=0.6666……

1/1 和 2/2 虽然都是纯循环小数,但因为它们相等,因此只计数一次;同样,1/3 和 2/6 也只计数一次。

这部分将提供一个将分数化为对应的小数的方法,如果你已经熟悉这个方法,你不必阅读本提示。

分数可以通过除法,用分子除以分母化为对应的小数。有些分数在除法过程中无法除尽,这样的分数在不断进行的除法过程中余数一定会重复出现。从商数的个位所对应的余数起,设第一次重复出现的余数前两次出现的位置所对应的商数位分别是小数点后第 a位和小数点后第 b 位(特殊地:如果其中一个对应的商数位是个位,则认为 a=0;不妨设 a<b),则其循环部分可以用小数点后第 a+1位到小数点后第 b位的循环来表示。

例如:在十进制下,将 511转化为小数时,个位开始的商数依次为 4,5,4,…,对应的余数分别为 6,5,6,…。余数第一次重复出现的位置是个位和小数点后第 2 位,那么 a=0,b=2

a=0,b=2即其循环部分可以用小数点第 1位到第 3位来表示。表示为:511=0.45454545…=0.4˙5˙。

在十进制下,将 16 转化为小数时,个位开始的商数依次为 1,6,6,…,对应的余数分别为 4,4,4,…。余数第一次重复出现的位置是小数点后第 1 位和小数点后第 2 位,即其循环部分可以用小数点后第 2 位来表示。表示为:16=0.1666……=0.16˙。

需要注意的是:商数重复出现并不代表进入了循环节。

Kelin的题解

题意:求\(\sum_{x=1}^n\sum_{y=1}^m\frac{x}{y}\)在\(k\)进制下能表示成循环节从第一位小数开始的无限循环小数或整数的最简分数个数

假设\(\frac{x}{y}\)的循环节长度为\(l\),则$ {\frac{xk^l}{y}}={\frac{x}{y}}$。

这里大括号表示其小数部分,意思就是把小数点往后挪\(l\)位,小数部分还是相同。比如\(1.123123\ldots\)小数点往后挪3位变成\(1123.123\ldots\)

参照10进制下小数点往后挪 \(l\) 位就是乘以 \(10^l\),那么 \(k\) 进制下小数点往后挪 \(l\) 位就是乘以 \(k^l\)

\[\{\frac{xk^l}{y}\}=\{\frac{x}{y}\}\\
\Rightarrow \frac{xk^l}{y}-\lfloor\frac{xk^l}{y}\rfloor=\frac{x}{y}-\lfloor\frac{x}{y}\rfloor\\
\Rightarrow xk^l-\lfloor\frac{xk^l}{y}\rfloor*y=x-\lfloor\frac{x}{y}\rfloor*y\\
\Rightarrow xk^l\equiv x\mod y
\]

题目要求最简分数,所以 \(\gcd(x,y)=1\)

\[xk^l\equiv x\mod y\\
\Rightarrow k^l\equiv1\mod y\\
\Rightarrow (k,y)=1\\
\Rightarrow Ans=\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=1][\gcd(j,k)=1]
\]

  • 考虑处理 \([\gcd(i,j)=1]\)

\[Ans=\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=1][\gcd(j,k)=1]\\
=\sum_{j=1}^m[\gcd(j,k)=1]\sum_{i=1}^n[\gcd(i,j)=1]\\
=\sum_{j=1}^m[\gcd(j,k)=1]\sum_{i=1}^n\sum_{d|i\wedge d|j}\mu(d)\\
=\sum_{j=1}^m[\gcd(j,k)=1]\sum_{d|j}\mu(d)\lfloor\frac nd\rfloor\\
=\sum_{d=1}^n\mu(d)\lfloor \frac nd\rfloor\sum_{j=1}^{\lfloor\frac md\rfloor}[\gcd(jd,k)=1]\\
\sum_{d=1}^n\mu(d)[\gcd(d,k)=1]\lfloor \frac nd\rfloor\sum_{j=1}^{\lfloor\frac md\rfloor}[\gcd(j,k)=1]
\]

观察式子,后面那个部分很支持整除分块,所以往这方面考虑。

设\(f(n)=\sum_{i=1}^n[\gcd(i,k)=1]=\lfloor\frac nk \rfloor\varphi(k)+f(n \mod k)\)。可以\(O(k\log k)\)预处理\(f(1\sim k)\)。

  • 考虑分析式子

我们可以把\(k\)表示成\(p^aq\),假设\(p\)是\(k\)最小的质因子。对于1到\(k\)中每一个数可以预处理出他的\(p,q\)。设

\[g(n,k)=\sum_{d=1}^n\mu(d)[\gcd(d,k)=1]\\
=\sum_{d=2}^n\mu(d)[\gcd(d,p)=1][\gcd(d,q)=1]
\]

因为\(p\)是质数,所以\(\gcd(d,p)=1\)或\(p\)。考虑容斥,在满足 \(\gcd(d,q)=1\)的\(\mu(d)\)中减去也满足\((d,p)=p\)的。即

\[g(n,k)=\sum_{d=1}^n\mu(d)[\gcd(d,q)=1]-\sum_{d=1}^{\lfloor \frac np\rfloor}\mu(dp)[\gcd(d,q)=1]\\
=g(n,q)-\sum_{d=1}^{\lfloor \frac np\rfloor}\mu(dp)[\gcd(d,q)=1]
\]

当\(\gcd(d,p)\neq 1\)时\(\mu(dp)=0\),所以\(d\)要满足\((d,p)=1\)

\[g(n,k)=g(n,q)-\sum_{d=1}^{\lfloor \frac np\rfloor}\mu(dp)[\gcd(d,q)=1][\gcd(d,p)]=1
\]

因为\(\mu\)是积性函数,所以拆开得

\[g(n,k)=g(n,q)-\mu(p)\sum_{d=1}^{\lfloor\frac np\rfloor}\mu(d)[\gcd(d,k)=1]\\
=g(n,q)+g(\lfloor \frac np\rfloor,k)
\]

边界是\(g(0,k)=0\),以及\(g(n,1)=\sum_{d=1}^n\mu(d)\)直接杜教筛。

复杂度是 \(O\) (( \(k\) 的质因子个数) \(\sqrt n+n^{\frac{2}{3}}\) )

#include<bits/stdc++.h>
#define il inline
#define co const
template<class T>T read(){
T data=0,w=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
return data*w;
}
template<class T>il T read(T&x) {return x=read<T>();}
typedef long long LL;
using namespace std; co int N=1e6+1,K=2001;
int n,m,k;
int pri[N],tot,mu[N];
int f[K],p[K],q[K];
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
void init(){
pri[1]=mu[1]=1;
for(int i=2;i<N;++i){
if(!pri[i]) pri[++tot]=i,mu[i]=-1;
for(int j=1;j<=tot&&i*pri[j]<N;++j){
pri[i*pri[j]]=1;
if(i%pri[j]==0){
mu[i*pri[j]]=0;
break;
}
mu[i*pri[j]]=-mu[i];
}
}
for(int i=2;i<N;++i) mu[i]+=mu[i-1];
for(int i=1;i<=k;++i) f[i]=f[i-1]+(gcd(i,k)==1);
// cerr<<"fk="<<f[k]<<endl;
for(int i=2;i<=k;++i){
for(int j=1;j<=tot;++j)
if(i%pri[j]==0) {p[i]=pri[j];break;}
for(q[i]=i/p[i];q[i]%p[i]==0;) q[i]/=p[i];
// if(k-i<=20) cerr<<i<<" p="<<p[i]<<" q="<<q[i]<<endl;
}
}
il int F(int n){
return n/k*f[k]+f[n%k];
}
typedef pair<int,int> pii;
map<pii,int> sg;
int G(int n,int k){
if(!n||n<N&&k==1) return mu[n];
if(sg.count(pii(n,k))) return sg[pii(n,k)];
if(k==1){
int ans=1;
for(int l=2,r;l<=n;l=r+1){
r=n/(n/l);
ans-=(r-l+1)*G(n/l,1);
}
return sg[pii(n,k)]=ans; // edit 1
}
return sg[pii(n,k)]=G(n,q[k])+G(n/p[k],k);
}
int main(){
read(n),read(m),read(k);
init();
// cerr<<"gnk="<<G(n,k)<<endl;
// cerr<<"fm="<<F(m)<<endl;
LL ans=0;
for(int l=1,r;l<=min(n,m);l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=(LL)(G(r,k)-G(l-1,k))*(n/l)*F(m/l); // edit 2:(n/l)
}
printf("%lld\n",ans);
return 0;
}

这题我n/k忘带括号然后WA了。现在想想下取整除法只有分母具有结合律。

「NOI2016」循环之美的更多相关文章

  1. LibreOJ2085 - 「NOI2016」循环之美

    Portal Description 给出\(n,m(n,m\leq10^9)\)和\(k(k\leq2000)\),求在\(k\)进制下,有多少个数值不同的纯循环小数可以表示成\(\dfrac{x} ...

  2. 「NOI2016」循环之美 解题报告

    「NOI2016」循环之美 对于小数\(\frac{a}{b}\),如果它在\(k\)进制下被统计,需要满足要求并且不重复. 不重复我们确保这个分数是最简分数即\((a,b)=1\) 满足要求需要满足 ...

  3. *LOJ#2085. 「NOI2016」循环之美

    $n \leq 1e9,m \leq 1e9,k \leq 2000$,求$k$进制下$\frac{x}{y}$有多少种不同的纯循环数取值,$1 \leq x \leq n,1 \leq y \leq ...

  4. LOJ 2085: 洛谷 P1587: bzoj 4652: 「NOI2016」循环之美

    题目传送门:LOJ #2085. 两个月之前做的傻题,还是有必要补一下博客. 题意简述: 求分子为不超过 \(n\) 的正整数,分母为不超过 \(m\) 的正整数的所有互不相等的分数中,有多少在 \( ...

  5. 「NOI2016」循环之美(小性质+min_25筛)

    传送门. 题解 感觉这题最难的是第一个结论. x/y首先要互质,然后如果在10进制是纯循环小数,不难想到y不是2.5的倍数就好了. 因为十进制下除以2和5是除得尽的. 必然会多出来的什么东西. 如果是 ...

  6. 【LOJ】#2085. 「NOI2016」循环之美

    题解 我们要求的其实是这个东西= = \(\sum_{i = 1}^{n}\sum_{j = 1}^{n}[(i,j) == 1][(j,k) == 1]\) 然后变一下形 \(\sum_{j = 1 ...

  7. 「NOI2016」优秀的拆分 解题报告

    「NOI2016」优秀的拆分 这不是个SAM题,只是个LCP题目 95分的Hash很简单,枚举每个点为开头和末尾的AA串个数,然后乘一下之类的. 考虑怎么快速求"每个点为开头和末尾的AA串个 ...

  8. 「NOI2016」网格 解题报告

    「NOI2016」网格 容易注意到,答案最多为2,也就是说答案为-\(1,0,1,2\)四种,考虑逐个判断. 无解的情况比较简单 如果\(nm\le c+1\),显然无解 如果\(nm=c+2\),判 ...

  9. 「NOI2016」区间 解题报告

    「NOI2016」区间 最近思维好僵硬啊... 一上来就觉得先把区间拆成两个端点进行差分,然后扫描位置序列,在每个位置维护答案,用数据结构维护当前位置的区间序列,但是不会维护. 于是想研究性质,想到为 ...

随机推荐

  1. vs中调试程序查看变量在内存中的内容的方法

    vs中调试程序 查看变量在内存中的内容的方法 https://blog.csdn.net/guojg1988/article/details/42922149 原文链接:http://www.sows ...

  2. Influx Sql系列教程二:retention policy 保存策略

    retention policy这个东西相比较于传统的关系型数据库(比如mysql)而言,是一个比较新的东西,在将表之前,有必要来看一下保存策略有什么用,以及可以怎么用 I. 基本操作 1. 创建re ...

  3. CF-Technocup3 D Optimal Subsequences

    D Optimal Subsequences http://codeforces.com/contest/1227/problem/D2 显然,每次求的k一定是这个序列从大到小排序后前k大的元素. 考 ...

  4. linux中安装python3.7

    linux中安装python3.7 1. 安装依赖包 yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite- ...

  5. LeetCode 32. 最长有效括号(Longest Valid Parentheses) 31

    32. 最长有效括号 32. Longest Valid Parentheses 题目描述 给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度. 每日一算法2019/6/ ...

  6. tomcat-修改端口--号

    1.背景 在默认情况下,tomcat的端口是8080,使用了两个tomcat,那么就需要修改其中的一个的端口号才能使得两个同时工作. 2.方法 2.1改动一 那么,如何修改tomcat的端口号呢?首先 ...

  7. 什么是REST 、RESTful 、RESTful API?

    介绍 自从Roy Fielding博士在2000年他的博士论文中提出Rest(Representational State Transfer)风格的软件架构模式后,REST就基本上迅速取代了复杂而笨重 ...

  8. Python基础系列讲解-自动控制windows桌面

    原链接:https://zhuanlan.zhihu.com/p/73001806 在使用PC时与PC交互的主要途径是看屏幕显示.听声音,点击鼠标和敲键盘等等.在自动化办公的趋势下,繁琐的工作可以让程 ...

  9. pychram 中 Terminal 中 git log 中文乱码解决办法

    添加环境变量 set LESSCHARSET=utf-8 执行以下命令 git config --global core.quotepath false 不成功执行以下命令 git config -- ...

  10. Nvidia Jetson TX2开发板学习历程(1)- 详细开箱、上电过程

    考试周已经结束了,开发板也已经到了.希望借着这个假期能够好好的利用这块开发板学习Linux系统以及Tensorflow的相关知识. 我打算将学习历程通过博客的方式写出来,作为自己的笔记,也可以供以后拿 ...