小红的循环节长度

简介: 小红的循环节长度

#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 被用作累乘的结果,随着循环的进行,它的值会不断增大,直到达到最终的幂次结果
目录
相关文章
|
3月前
|
算法
LeetCode算法题---无重复字符的最长子串、寻找两个正序数组的中位数(三)
LeetCode算法题---无重复字符的最长子串、寻找两个正序数组的中位数(三)
52 0
|
11月前
|
算法
arr = [1,2,5,8,9,10,20,30,40] 有一个从小到大排序好的数组,现在输入一个数,要求按照原来的规律插入到数组中
arr = [1,2,5,8,9,10,20,30,40] 有一个从小到大排序好的数组,现在输入一个数,要求按照原来的规律插入到数组中
|
3月前
给定一个长度为n的数组,请将数组中元素按照奇偶性重新划分,所有奇数靠左边,所有偶数靠右边,然后分别对奇数、偶数部分进行排序
给定一个长度为n的数组,请将数组中元素按照奇偶性重新划分,所有奇数靠左边,所有偶数靠右边,然后分别对奇数、偶数部分进行排序
38 1
|
3月前
逆序数打印
该内容是关于编程计算正整数的逆序数。用户输入一个正整数,程序需输出其逆序数,即数字顺序反转后的数。文章中包含两张图片作为示例,但图片数据未显示。
27 0
|
3月前
1493.删掉一个元素以后全为1的最长子数组
1493.删掉一个元素以后全为1的最长子数组
22 0
|
3月前
每日一题(づ ̄3 ̄)づ╭❤~(数字在升序数组中出现的次数,整数转换)
每日一题(づ ̄3 ̄)づ╭❤~(数字在升序数组中出现的次数,整数转换)
21 0
|
算法 Java
2015 蓝桥杯省赛部分题整理(九数组分数,牌型种数,串逐位和,循环节长度,打印菱形)
2015 蓝桥杯省赛部分题整理(九数组分数,牌型种数,串逐位和,循环节长度,打印菱形)
78 0
|
存储 机器学习/深度学习
母牛的故事 替换空格 二进制中1的个数 不使用第三个变量交换a,b的值
母牛的故事 替换空格 二进制中1的个数 不使用第三个变量交换a,b的值
79 0
找出列表中的偶数位元素
找出列表中的偶数位元素
74 0
|
算法 C语言
剑指Offer 第53题:数字在升序数组中出现的次数
剑指Offer 第53题:数字在升序数组中出现的次数
123 0
剑指Offer 第53题:数字在升序数组中出现的次数