小红的循环节长度

简介: 小红的循环节长度

#include <iostream>
typedef long long ll;
using namespace std;
ll FN(ll x)
{
  ll a = x;
  for (ll i = 2; i * i <= x; i++)
  {
    if (x % i == 0)
    {
      a = a / i * (i - 1);
      while (x % i == 0)
      {
        x /= i;
      }
    }
  }
  if (x > 0)
  {
    a = a / x * (x - 1);
  }
  return a;
}
ll fp(ll a, ll b, ll p)
{
  __int128 an = 1;
  for (a %= p; b; a = (__int128)a * a % p, b >>= 1)
  {
    if (b & 1)
    {
      an = (__int128)an * a % p;
    }
  }
  return an;
}
ll gcd(ll a, ll b)
{
  return b ? gcd(b, a % b) : a;
}
int main()
{
  ll p, q;
  cin >> p >> q;
  q /= gcd(p, q);
  ll s2 = 0, s5 = 0;
  while (q % 2 == 0)
  {
    s2++;
    q /= 2;
  }
  while (q % 5 == 0)
  {
    s5++;
    q /= 5;
  }
  if (q == 1)
  {
    cout << -1 << endl;
  }
  else
  {
    ll e = FN(q);
    ll mi = 1e18;
    for (ll i = 1; i * i <= e; i++)
    {
      if (e % i == 0)
      {
        if (fp(10, i, q) == 1)
        {
          mi = min(mi, i);
        }
        if (fp(10, e / i, q) == 1)
        {
          mi = min(mi, e / i);
        }
      }
    }
    cout << max(s2, s5) << " " << mi << endl;
  }
  return 0;
}

解决一个数论问题,其目的是确定一个分数 p/q(其中 pq 是输入的正整数且已约简过)的小数表示中循环节的长度。首先,代码分为几个主要函数:

  1. FN(ll x) 函数: 这个函数计算一个整数 x 的欧拉函数 ,即小于等于 x 且与 x 互质的正整数个数。通过分解质因数并应用欧拉定理的性质计算得出。
  2. fp(ll a, ll b, ll p) 函数: 这是一个快速幂函数,计算 ab 次方对 p 取模的结果,利用二进制快速幂算法实现,提高计算效率。
  3. gcd(ll a, ll b) 函数: 计算两个整数的最大公约数,采用辗转相除法(欧几里得算法)
  4. main() 函数: 主函数接收输入的分数分子 p 和分母 q,首先通过约简使得 q 不含质因子 2 和 5 的多余幂次(不影响循环节长度)。然后分别计算 q 中质因数 2 和 5 的指数(记作 s2s5),初步判断循环节长度至少为两者较大者。
    接下来计算 q 的欧拉函数 \phi(q),并通过快速幂函数 fp() 查找使 10 的某个幂次对 q 取模等于 1 的最小指数,即 10^mi ≡ 1 (mod q),这个指数 mi 就是循环节的长度。这是因为 10^mi 代表的是循环节的周期。
    输出循环节长度的最大可能值(max(s2, s5))和通过搜索得到的 mi,两者中较大的那个作为最终答案。如果 q 不含有除了 2 和 5 以外的质因数,则输出 -1,表示分数 p/q 是有限小数。
  5. 在C++编程中,\_\_int128 是一种特定编译器支持的128位整数类型。这意味着它可以存储一个128位(16字节)的整数值,比常规的intlonglong long类型所能表示的范围更大。
    在这段代码中,
__int128 an = 1;
  1. 这条语句初始化了一个名为 an 的128位整数变量,并将其设置为1。由于后面代码涉及到大数的计算(快速幂算法),使用__int128是为了能够容纳更大的中间计算结果,确保计算过程不会发生溢出。在这个上下文中,an 被用作累乘的结果,随着循环的进行,它的值会不断增大,直到达到最终的幂次结果
目录
相关文章
|
算法 Java
2015 蓝桥杯省赛部分题整理(九数组分数,牌型种数,串逐位和,循环节长度,打印菱形)
2015 蓝桥杯省赛部分题整理(九数组分数,牌型种数,串逐位和,循环节长度,打印菱形)
107 0
|
9月前
|
存储 人工智能 BI
小红的排列构造(dp优化)
小红的排列构造(dp优化)
78 0
|
存储 算法 C++
Day6——有效的字母异位词、两个数组的交集、快乐数、两数之和(哈希)
Day6——有效的字母异位词、两个数组的交集、快乐数、两数之和(哈希)
110 0
|
算法 容器
力扣17 - 电话号码的字母组合【回溯、哈希映射、队列】
对应力扣.17电话号码的字母组合,详细动画和图示讲解,带你快乐刷题
115 0
力扣17 - 电话号码的字母组合【回溯、哈希映射、队列】
【LeetCode13】罗马数字转整数(简单模拟+哈希)
简单题,读懂题意。如果右边的数比当前的数大,则当前数需要加个负号,如IV是5-1=4;如果右边的数比当前的数字小,则都是加法(注意最后一个数也是用加法的)。 三、代码
130 0
【LeetCode13】罗马数字转整数(简单模拟+哈希)
7-100 倒数第N个字符串 (15 分)
7-100 倒数第N个字符串 (15 分)
78 0
L1-050 倒数第N个字符串 (15 分)
L1-050 倒数第N个字符串 (15 分)
99 0
[解题报告](第21讲) 字符串算法(一) - 字符串遍历(2)
[解题报告](第21讲) 字符串算法(一) - 字符串遍历
[解题报告](第21讲) 字符串算法(一) - 字符串遍历(2)
|
算法 机器人
[解题报告](第21讲) 字符串算法(一) - 字符串遍历(1)
[解题报告](第21讲) 字符串算法(一) - 字符串遍历
[解题报告](第21讲) 字符串算法(一) - 字符串遍历(1)

热门文章

最新文章