(HDU)1005 -- Number Sequence(数列)

问题描述
数列定义如下:

f(1)= 1,f(2)= 1,f(n)=(A * f(n-1)+ B * f(n-2))mod 7。

给定A,B和n,你要计算f(n)的值。

输入
输入由多个测试用例组成。 每个测试用例在一行(1 <= A,B <= 1000,1 <= n <= 100,000,000)中包含3个整数A,B和n。三个零表示输入结束,此测试用例不进行处理。

输出
对于每个测试用例,在一行上输出f(n)的值。

样例输入
1 1 3
1 2 10
0 0 0

样例输出
2
5

问题

注意这道题n的范围,1≤n≤1000000000,要小心超时超内存的问题。

看到题目直接写往往会忽视很多细节问题,给出公式的题目注意看看有没有规律。

mod是取模的意思,这里可以认为是取余数。

所谓的同余,顾名思义,就是许多的数被一个数d去除,有相同的余数。d数学上的称谓为模。如a=6,b=1,d=5,则我们说a和b是模d同余的。因为他们都有相同的余数1。
       数学上的记法为:
       a≡ b(mod d)
       可以看出当n<d的时候,所有的n都对d同商,比如时钟上的小时数,都小于12,所以小时数都是模12的同商.
对于同余有三种说法都是等价的,分别为:
       (1) a和b是模d同余的.
       (2) 存在某个整数n,使得a=b+nd .
       (3) d整除a-b.
       可以通过换算得出上面三个说法都是正确而且是等价的.
       基本定律:
       同余公式也有许多我们常见的定律,比如相等律,结合律,交换律,传递律….如下面的表示:
       1)a≡a(mod d)
       2)对称性 a≡b(mod d)→b≡a(mod d)
       3)传递性 (a≡b(mod d),b≡c(mod d))→a≡c(mod d)
       如果a≡x(mod d),b≡m(mod d),则
           4)a+b≡x+m (mod d)
           5)a-b≡x-m (mod d)
           6)a*b≡x*m (mod d )
           7)a/b≡x/m (mod d)
       8)a≡b(mod d)则a-b整除d
       9)a≡b(mod d)则a^n≡b^n(mod d)
      10)如果ac≡bc(mod m),且c和m互质,则a≡b(mod m)
      模运算的运算规则:
      (a + b)  mod  p = (a  mod  p + b  mod  p)  mod  p            (1)
      (a - b)  mod  p = (a  mod  p - b  mod  p)  mod  p              (2)
      (a * b)  mod  p = (a  mod  p * b  mod  p)  mod  p              (3)
      a^b  mod  p = ((a  mod  p)^b)  mod  p                              (4)
      结合率: ((a+b)  mod  p + c)  mod  p = (a + (b+c)  mod  p)  mod  p (5)
                     ((a*b)  mod  p * c) mod  p = (a * (b*c)  mod  p)  mod  p     (6)
      交换率: (a + b)  mod  p = (b+a)  mod  p                 (7)
                     (a * b)  mod  p = (b * a)  mod  p                 (8)
      分配率: ((a +b) mod  p * c)  mod  p = ((a * c)  mod  p + (b * c)  mod  p)  mod  p (9)
      重要定理:若a≡b ( mod  p),则对于任意的c,都有(a + c) ≡ (b + c) ( mod p);(10)
                        若a≡b ( mod  p),则对于任意的c,都有(a * c) ≡ (b * c) ( mod p);(11)
                        若a≡b ( mod  p),则对于任意的c,都有ac≡ bc ( mod p);     (13)

本文地址:http://blog.csdn.net/a359680405/article/details/41675143

了解内容:模运算性质

对于公式 f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7,为了防止溢出,改成 f(n) = (A mod 7 * f(n - 1) + B mod 7* f(n - 2))mod 7

(如果看不懂改写原因就看一下上面的了解内容,或者自己写几个例子验证。这题A和B范围比较小,其实不改也可以。)

f(n)自身是保证在0-6的整数范围内的,同样f(n-1)和f(n-2)只有这七种取值。

f(n)是由f(n-1)和f(n-2)确定的,因为A和B是一个确定的值,对整个公式没有影响。

用映射的思想来看,一对f(n-1)和f(n-2)只能映射一个f(n),

所以f(n)的计算 最多 只有 49种可能,如果你还是理解不了,看下面的表格...

假设A=2,B=1...但是循环周期不是49(这是最糟糕的情况)。

fn f(n-1)
0 1 2 3 4 5 6
f(n-2) 0 0 2 4 6 1 3 5
1 1 3 5 0 2 4 6
2 2 4 6 1 3 5 0
3 3 5 0 2 4 6 1
4 4 6 1 3 5 0 2
5 5 0 2 4 6 1 3
6 6 1 3 5 0 2 4

如果有连续的两项,在前面的数列中出现过,最小循环节就找到了(注意不一定是出现连续两个1,1的时候,即出现f(1)和f(2))

eg:1  1  3  4  1  6  1  3(1和3在前面出现过了,最小循环节就是13416)

找到了最小循环节,代码就容易写出来了。

下面的写法是直接将49个数作为循环节,但是不是最小循环节(周期函数不是有最小正周期嘛)。

 1 #include <iostream>
 2 using namespace std;
 3 int arr[50];
 4 int main()
 5 {
 6     int n,a,b;
 7     arr[1]=arr[2]=1;
 8     while(cin>>a>>b>>n)
 9     {
10         if(a==0&&b==0&&n==0)
11             break;
12         int minn=n<50?n:50;//一个小小的优化
13         for(int i=3; i<=minn; i++)
14         {
15             arr[i]=(a*arr[i-1]+b*arr[i-2])%7;
16         }
17         cout<<arr[n%49]<<endl;
18
19     }
20     return 0;
21 }  

不寻找最小循环节,直接用49作为周期的写法

这个写法比较麻烦,但是也算一种拓展:

 1 #include <cstring>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 using namespace std;
 5
 6 int rec[60];
 7
 8 int main()
 9 {
10     int a, b, n;
11     rec[0] = rec[1] = rec[2] = 1;
12     while( scanf( "%d %d %d", &a, &b, &n ), a | b | n )
13     {
14         int beg, end, flag = 0;
15         for( int i = 3; i <= n && !flag; ++i )
16         {
17             rec[i] = ( a * rec[i-1] + b * rec[i-2] ) % 7;
18             for( int j = 2; j <= i - 1; ++j )
19             {
20                 if( rec[i] == rec[j] && rec[i-1] == rec[j-1] )
21                 {
22                     beg = j, end = i;
23                     flag = 1;
24                     break;
25                 }
26             }
27         }
28         if( flag )
29         {
30             printf( "%d\n", rec[beg+(n-end)%(end-beg)] );
31         }
32         else
33             printf( "%d\n", rec[n] );
34     }
35     return 0;
36 }

寻找最小循环节

时间: 2024-10-08 14:55:37

(HDU)1005 -- Number Sequence(数列)的相关文章

HDU 1005 Number Sequence (数学规律)

Number Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 104190    Accepted Submission(s): 25232 Problem Description A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A

HDU 1005 Number Sequence(数论)

HDU 1005 Number Sequence(数论) Problem Description: A number sequence is defined as follows:f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. Given A, B, and n, you are to calculate the value of f(n). Input The input consists of multiple

HDU 1005 Number Sequence(数列)

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) [Description] [题目描述] A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. Given A, B, and n, you are to calculate the

HDU 1005 Number Sequence【多解,暴力打表,鸽巢原理】

Number Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 175657    Accepted Submission(s): 43409 Problem Description A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A

HDU 1005 Number Sequence 数学

Problem Description A number sequence is defined as follows:f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.Given A, B, and n, you are to calculate the value of f(n). Input The input consists of multiple test cases. Each test case cont

HDU 1005 Number Sequence 矩阵快速幂

Number Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 236241    Accepted Submission(s): 60070 Problem Description A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A

HDU 1005 Number Sequence 矩阵乘法 Fib数列

原题: http://acm.hdu.edu.cn/showproblem.php?pid=1005 题目大意: 按规律求出第n项. 由矩阵乘法我们可以知道: 所以对于fib数列我们可以用矩阵来求,由于矩阵可以左乘右乘,所以我们可以用快速幂来优化. #include<iostream> #include"string.h" #include<stdio.h> using namespace std; const int bc=2; const int mod =

HDU - 1005 Number Sequence(简单矩阵快速幂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1005 题意:f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. 就是这道题目,然而找了一晚上的错误 \("▔□▔)/\("▔□▔)/\("▔□▔)/. 1 #include <iostream> 2 #include <cstring> 3 using namespace std;

HDU 1005 Number Sequence (循环节)

首先暴力打表就很容易发现有循环节,于是一开始的写法是直接暴力找循环节,结果一直WA, 原因是有的循环并不是从1,1开始的,详细有证明戳这里:http://acm.hdu.edu.cn/discuss/problem/post/reply.php?postid=19818&messageid=1&deep=0 于是借鉴了大神的思路,因为%7,故可用v[7][7]来记录 f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.这个状态.若出现相同的状态,则证明出现

51nod 1126 求递推序列的第N项 &amp;&amp; hdu - 1005 Number Sequence (求周期)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1126 http://acm.hdu.edu.cn/showproblem.php?pid=1005 注意上面一题和下面一题的区别,上面A,B可能取负数,但是mod跟c++中%是不一样的,mod只会得到非负数,两次跳进这个坑了. 然后就找周期,只要f[i-1]==1&&f[i]==1就可以跳出,然后i-2就是周期,输出n%(i-2)的时候,要注意如果等于0的话,其实