11.求循环节

11.求循环节

成绩 10 开启时间 2014年11月12日 Wednesday 18:25
折扣 0.8 折扣时间 2014年11月30日 Sunday 23:55
允许迟交 关闭时间 2014年12月7日 Sunday 23:55

对于任意的真分数 N/M ( 0 < N < M ),均可以求出对应的小数。如果采用链表存储各位小数,对于循环节采用循环链表表示,则所有分数均可以表示为如下链表形式。

tu

输入: N M

输出: 整个循环节

要求:
 
编写一个尽可能高效的查找循环节起始点的函数: NODE * find( NODE * head, int * n ) 。函数的返回值为循环节的起点(即图中的指针p),n为循环节的长度。

说明:提交程序时请同时提交将分数转换为小数的函数 change( int n, int m, NODE * head ) (前面题目中已经编写)。

预设代码

前置代码
  1. /* PRESET CODE BEGIN - NEVER TOUCH CODE BELOW */  
  2.  
  3. #include <stdio.h>  
  4. #include <stdlib.h>  
  5.   
  6. typedef struct node  
  7. {   int         data;  
  8.     struct node * next;  
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
可以使用数学归纳法解这个问题,从而避免暴力枚举。 首先观察题目中给出的数列,我们可以发现:第 $i$ 项由 $i-1$ 项乘以 10 再加上 1 构成。即: $$ a_i = a_{i-1} \times 10 + 1 $$ 例如,第 2 项 $= 1 \times 10 + 1 = 11$,第 3 项 $= 11 \times 10 + 1 = 111$。 接下来,我们将数列中的每一项除以 7 取余数,然后观察余数序列: $$ a_1 \bmod 7, a_2 \bmod 7, a_3 \bmod 7, \cdots $$ 可以发现,余数序列为 1, 4, 5, 2, 0, 1, 4, 5, 2, 0, ...,即以 1, 4, 5, 2, 0 循环出现。因此,我们可以通过分别出这些数的前缀和来计算数列的和除以 7 的余数。 具体来说,设 $s_i$ 表示余数序列前 $i$ 项的和,则: $$ s_i = \sum_{j=1}^{i} a_j \bmod 7 $$ 根据前面的推导,余数序列是循环出现的,因此我们只需要计算出一个循环(即 1, 4, 5, 2, 0),然后计算循环中的前缀和即可。例如,设 $t$ 表示循环的长度,则: $$ s_n = s_{n \bmod t} + \frac{n}{t} \times s_t $$ 最后,我们只需要先循环的前缀和 $s_t$,然后计算出 $s_n$ 即可。 下面是完整的 C++ 代码实现: ```c++ #include <iostream> #include <vector> using namespace std; int main() { int n; cin >> n; // 计算循环的前缀和 vector<int> prefix_sum = {1, 5, 0, 0, 0}; for (int i = 1; i < prefix_sum.size(); i++) { prefix_sum[i] = (prefix_sum[i-1] * 10 + 1) % 7; } // 计算循环的长度 int t = 5; while (prefix_sum[t % 5] != 1) { t++; } // 计算数列的和除以 7 的余数 vector<int> sum(t); for (int i = 0; i < t; i++) { sum[i] = prefix_sum[i]; if (i > 0) { sum[i] = (sum[i] + sum[i-1]) % 7; } } int result = (sum[(n-1) % t] + (n-1) / t * sum[t-1]) % 7; cout << result << endl; return 0; } ``` 时间复杂度为 $O(1)$,可以通过本题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值