题目名称 1047. [Nescafé 18] 理科男
输入输出 kubi.in/out
难度等级
时间限制 1000 ms (1 s)
内存限制 128 MiB
测试数据 10
题目来源 GravatarMakazeu 于2012-08-24加入
开放分组 全部用户
提交状态
分类标签
分享题解
通过:3, 提交:11, 通过率:27.27%
Gravatar粘粘自喜 100 0.018 s 0.06 MiB C++
GravatarHakurou! 100 0.042 s 0.06 MiB C++
Gravatar+1s 100 0.171 s 0.20 MiB C++
Gravatar+1s 50 0.113 s 0.23 MiB C++
GravatarMakazeu 50 5.114 s 0.31 MiB C++
GravatarHakurou! 40 6.024 s 0.18 MiB C++
GravatarHakurou! 40 6.032 s 0.27 MiB C++
GravatarHakurou! 0 0.044 s 0.03 MiB C++
Gravatar+1s 0 0.130 s 0.17 MiB C++
GravatarHakurou! 0 10.008 s 0.25 MiB C++
关于 理科男 的近10条评论(全部评论)
首先把 A / B 约分成既约分数。设 a[1] = A,r[n] 为原分数小数点后第 n 位的数。
显然有 r[1] = floor(K * a[1] / B)。
剩下来的余数 a[2] = K * a[1] mod B。
依此类推我们有 r[n] = floor(K * a[n] / B),a[n] = K * a[n - 1] mod B。
不难发现如果 a[p] = a[q](p < q),那么小数点后第 p 位到第 q - 1 位这一段就可以视为一个循环节。
暴力计算数列 a,找到第一个与前面重复的项,就可以找到最短循环节了。
这个重复的项前面的部分导出混循环部分
如果最早在 p 处计算到 a[p] = 0,那么原分数就是一个小数点后有 p - 1 位的有限小数。
以上便是 50 分的解法。
下面我们对 a 数列的性质做一些讨论。
如果 (B, K) = 1,对于任意的 i 都有 (a[i], B) = 1。
设 K' 为 K 模 B 时的乘法逆元,即 KK' mod B = 1。由乘法逆元的性质 K' 存在且唯一。
假设最早出现重复的位置是 a[p] = a[q] (p < q)。
如果 p != 1,那么 a[p - 1] = K' * a[p] mod B = K' * a[q] mod B = a[q - 1]。
也就是出现了更早的重复,与题设矛盾。所以显然有 p = 1。
这时,显然原分数是一个纯循环小数,且最短循环节长度是 q - 1。
设 x = q - 1。显然 a[q] = a[1] * K^x mod B = a[1],于是 K^x mod B = 1。
这就转化成了求 K 模 B 的阶的问题了。
由欧拉定理 K^phi(B) = 1 (mod B),由阶的性质 x | phi(B)。
我们可以将 phi(B) 分解素因数,并初始化 x = phi(B)。
之后考虑 phi(B) 的每个素因数 p。如果 K^(x/p) = 1 (mod B),就 x ← x / p,并继续试除 p。否则转下一个素因数。这样就可以求出 K 模 B 的阶了,这就是最短循环节的长度
如果 (B, K) > 1,那么 (a[2], B) > 1。设 (a[2], B) = g,不难发现对于任意的 i ≥ 2,有 g | (a[i], B)。
不妨设 B' = B / g,a'[i] = a[i] / g (i ≥ 2)。
若此时 (B', K) = 1,就转化为了上面的情况。否则继续这个过程。
如果上面的转换进行了 T 次,由于 a[1] 到 a[T] 与后面 a 数列的循环无关。
卡一下范围便会知道循环节的最后一个数字与混循环部分最后一个数字一定不相等。
于是原分数的混循环长度就是 T 了。
特殊地,如果在 T 次转换之后得到的最后一个 B = 1,那么之后 a 数列的值全为 0。这时我们可以断言原分数是一个小数点后有 T 位的有限小数。
以上便是 100 分的做法。
搬自CODE[VS]P2487
PS:这年头1星题都这么难了,这让蒟蒻怎么活
GravatarHakurou!
2016-08-25 09:35 3楼
这个背景让我闻到了一丝2333的味道~
GravatarHzoi_
2016-02-15 15:30 2楼
配图是什么回事。
GravatarEzio
2014-09-22 21:59 1楼

1047. [Nescafé 18] 理科男

★   输入文件:kubi.in   输出文件:kubi.out   简单对比
时间限制:1 s   内存限制:128 MiB
背景 Background
    吃过草莓刨冰之后,Vani和cl有些疲倦地坐在一个长椅上。
  “呐,玩得开心吗?”Vani忽然问道。
  “嗯……很,很开心的说。”
  “那么,我有一个问题想要问你呢。”
  cl的脸有点红了起来。
  “嗯……好吧。问、问吧……我会告诉你的哦……”
  “那好。对于一个分数A / B……”
  “嗯……哎?哎?!”
  “……就是这个问题。我觉得这个问题好纠结啊……”
  Vani淡定地说完这句话。

  “啊?!哈啊?!”

描述 Description
    对于给定的分数 A / B,求其在 K 进制下是有限小数还是循环小数。如果是有限小数,求小数点后的位数;如果是循环小数,则求混循环部分和循环节的长度又分别是多少。
  注意,循环节指的是最短循环节,且混循环部分的长度也指最短。
输入格式 Input Format
    第一行一个正整数 T,表示测试数据的数目。
  每个测试数据包含三个空格分隔的整数 A, B, K。含义如题目所示。

输出格式 Output Format
    对于每个测试数据,在单独的一行内输出两个空格分隔的整数 M, R。
  其中 M 表示混循环部分的长度,R 表示循环节的长度。
  如果 A / B 在 K 进制下是有限小数,则 R = 0,M 为小数点后面的位数;如果 A / B 在 K 进制下是纯循环小数,则 M = 0。

样例输入 Sample Input

3
1 8 10
17 99 10
217 990 10

样例输出 Sample Output 

3 0
0 2
1 2

时间限制 Time Limitation
  各个测试点1s
注释 Hint
    对于 50% 的数据,B≤100000。
  对于 100% 的数据,1≤A