列表

详情


NC256768. 小红的循环节长度

描述

小红知道任意分数都可以写成小数的形式,且一定是有限小数或无限循环小数中的一种。
小红想知道,分数的循环节前面部分的长度、以及循环节的长度是多少?

输入描述

两个正整数 pq,代表分子和分母。

输出描述

如果p/q为有限小数,则输出-1。
否则输出循环节前面部分的长度、以及循环节的长度。
请注意,循环节前面的长度要尽可能小,例如1/7=0.1428571428571……,那么循环节前面的长度为0。

示例1

输入:

1 6

输出:

1 1

说明:

\frac{p}{q}=0.16666...
循环节前面部分长度是1,循环节长度是1。

示例2

输入:

6 7

输出:

0 6

说明:

\frac{6}{7}=0.857142857142...
循环节前面部分长度是0,循环节长度是6。

示例3

输入:

1 4

输出:

-1

说明:

\frac{1}{4}=0.25
为有限小数。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 21ms, 内存消耗: 400K, 提交时间: 2023-08-09 09:12:21

#include<bits/stdc++.h>
using namespace std;
long long phi(long long x){
    long long i;
    long long res=x;
    for(i=2;i*i<=x;i++){
        if(x%i==0){
            res=res/i*(i-1);
            while(x%i==0)x/=i;
        }
    }
    if(x>1)res=res/x*(x-1);
    return res;
}
long long power(__int128 a,long long b,long long p){
    __int128 res=1;
    while(b){
        if(b&1)res=res*a%p;
        b>>=1;
        a=a*a%p;
    }
    return res;
}
int main(){
    long long p,q,i,c2=0,c5=0;
    cin>>p>>q;
    q/=__gcd(p,q);
    while(q%2==0)q/=2,c2++;
    while(q%5==0)q/=5,c5++;
    if(q==1)return cout<<-1,0;
    long long temp=phi(q);
    long long mi=1e16;
    for(i=1;i*i<=temp;i++){
        if(temp%i==0){
            if(power(10,i,q)==1)mi=min(mi,i);
            if(power(10,temp/i,q)==1)mi=min(mi,temp/i);  
        }
    }
    cout<<max(c2,c5)<<' '<<mi;
}

C++(clang++ 11.0.1) 解法, 执行用时: 21ms, 内存消耗: 412K, 提交时间: 2023-08-07 19:27:13

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
int p,q;
int check(int x){
	int res=x;
	for(int i=2;i*i<=x;i++){
		if(x%i==0){
			res=res/i*(i-1);
			while(x%i==0)x/=i;
		}
	}
	if(x>1)res=res/x*(x-1);
	return res;
}
int qim(__int128 a,int y,int z){
	__int128 res=1;
	while(y){
		if(y%2)res*=a;
		res%=z;
		a*=a;
		a%=z;
		y/=2;
	}
	return res%z;
}
signed main(){
	cin>>p>>q;
	int a=0,b=0;
	q/=__gcd(p,q);
	while(q%2==0)q/=2,a++;
	while(q%5==0)q/=5,b++;
	if(q==1){
		cout<<-1<<endl;
	}else{
		int tt=check(q);
		int minn=1e16;
		for(int i=1;i*i<=tt;i++){
			if(tt%i==0){
				if(qim(10,i,q)==1)minn=min(minn,i);
				if(qim(10,tt/i,q)==1)minn=min(minn,tt/i);
			}
		}
		cout<<max(a,b)<<" "<<minn<<endl;
	}
	return 0;
}

pypy3 解法, 执行用时: 98ms, 内存消耗: 24076K, 提交时间: 2023-08-08 11:52:10

import math
def phi(x: int) -> int:
    ans, i = x, 2
    while i * i <= x:
        if x % i == 0:
            ans = ans // i * (i - 1)
            while x % i == 0: x //= i 
        i += 1
    if x > 1: ans = ans // x * (x - 1)
    return ans
 
p, q = map(int, input().split())
g = math.gcd(p, q)
p //= g
q //= g # 化简
c2, c5 = 0, 0
while q % 2 == 0:
    q //= 2
    c2 += 1
while q % 5 == 0:
    q //= 5
    c5 += 1
if q == 1:
    print(-1)
    exit(0)
phiq = phi(q) # 拿到欧拉函数的值
ans, i = phiq, 2 # 找到最小的循环节
while i * i <= phiq:
    if phiq % i == 0: # 是因子
        if pow(10, i, q) == 1: ans = min(ans, i)
        if pow(10, phiq // i, q) == 1: ans = min(ans, phiq // i)
    i += 1
print(max(c2, c5), ans)

Python3 解法, 执行用时: 467ms, 内存消耗: 4656K, 提交时间: 2023-08-06 20:28:42

import math
p, q = map(int, input().split())
g = math.gcd(p, q)
p //= g
q //= g
c2 = 0
c5 = 0
while q % 2 == 0:
    q //= 2
    c2 += 1
while q % 5 == 0:
    q //= 5
    c5 += 1
if q == 1:
    print("-1")
    exit(0)

rq = q
mod = q
i = 2
while i*i <= q:
    if q % i == 0:
        rq //= i
        rq *= (i-1)
        while q % i == 0:
            q //= i
    i += 1
if q > 1:
    rq //= q
    rq *= (q-1)

ans = rq
i = 1
while i*i <= rq:
    if rq % i == 0:
        if pow(10, i, mod) == 1:
            ans = min(ans, i)
        if pow(10, rq//i, mod) == 1:
            ans = min(ans, rq//i)
    i += 1
print(max(c2, c5), ans)

上一题