Number Sequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 178776 Accepted Submission(s): 44428
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 contains 3 integers A, B and n on a single line (1 <= A, B <= 1000, 1 <= n <= 100,000,000). Three zeros signal the end of input and this test case is not to be processed.
Output
For each test case, print the value of f(n) on a single line.
Sample Input
1 1 3
1 2 10
0 0 0
Sample Output
2
5
Author
CHEN, Shunbao
Source
ZJCPC2004
思路
尝试了下循环n次求解f(n),超时。
观察到f(n)在[0,6]之间,数字是很神奇的,会产生循环,且a和b是固定的,f(n)可由f(n-1)和f(n-2)来确定。在判断周期时,只需判断存在f(i)=f(i+T)和f(i-1+T)=f(i-1),即可知道周期为T。
注意f(n)可能存在这种情况:1 1 2 3 4 5 2 3 4 5,f(1)和f(2)不在循环里(一开始卡在这一直超时)
AC代码一
#include<iostream>
#include<stdio.h>
using namespace std;
int g[100000002];
int main()
{
int fn1, fn2, fn,s;
int a, b, n,j;
while (scanf("%d%d%d", &a, &b, &n)!=EOF && a+b+n) {
fn1 = fn2 = fn = 1;
g[1] = g[2] = 1;
s = 0;
for (long i = 3; i <= n; i++)
{
fn = (a * fn1 + b * fn2) % 7;
g[i] = fn;
for ( j = 2; j<i; j++)
if (g[i - 1] == g[j - 1] && g[i] == g[j])//此题可以这样做的原因就是 2个确定后就可以决定后面的
{
s = i - j;
//cout<<j<<" "<<s<<" >>"<<i<<endl;
break;
}
/*if (fn == 1 && fn1 == 1) {
s = i - 1;
}*/
if (s != 0)
{
fn = g[(n-j)%s+j];
break;
}
fn2 = fn1;
fn1 = fn;
}
printf("%d\n", fn);
}
return 0;
}
进行一次优化
#include<iostream>
#include<stdio.h>
using namespace std;
int g[48 + 5];
int main()
{
int a, b, n, s;
long i;
while (scanf("%d%d%d", &a, &b, &n) != EOF && a + b + n) {
g[1] = g[2] = 1;
s = 0;
for (i = 3; i <= n; i++)
{
g[i] = (a * g[i - 1] + b * g[i - 2]) % 7;
if ((i>4) && g[i] == g[4] && g[i - 1] == g[3]) {
s = i - 4;
}
if (s != 0)
{
g[0] = g[(n - 4) % s + 4];
break;
}
}
printf("%d\n", i>n ? g[n]: g[0] );
}
return 0;
}
第二种方案求周期
有个非常坑的地方:f[k++]一直给我wa,我换成f[k],k++,才ac。
AC代码
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int N = 100;
int f[N], m[8][8];
int main()
{
int n, a, b, k = 3,s,x;
while (scanf("%d%d%d", &a, &b, &n) != EOF && a + b + n)
{
k = 3;
memset(m, 0, sizeof(m));
f[1] = f[2] = 1;
while (!m[f[k - 1]][f[k - 2]])
{
m[f[k - 1]][f[k - 2]] = k;
f[k] = (a*f[k - 1] + b*f[k - 2])%7;
k++;
// printf("f(%d)=%d ", k - 1, f[k - 1]);
}
x = m[f[k - 1]][f[k - 2]];
// printf("\ns=%d f[0]=%d\n", s, f[0]);
printf("%d\n", n < k ? f[n] : f[(n - (x)) % (k - x) + (x)]);
}
}
第三种网上贼屌的代码
#include<stdio.h>
int main()
{
int a,b,n,i,arr[49]={1,1};
while(scanf("%d%d%d",&a,&b,&n)&&(a|b|n))
{
for(i=2;i<49;i++)
arr[i]=(a*arr[i-1]+b*arr[i-2])%7;
printf("%d\n",arr[(n-1)%49]);//数组下标从0开始,所以n先减1
}
return 0;
}