循环节(hdoj1005)

一 问题描述

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).

二 解法

显然,由于取余的关系,连续的两个数f[i][j]( 0 <= i,j <= 6)出现的情况最多7×7=49种,故只要知道前51个数,定能够出现一个循环节(鸽巢原理)。
故只要记录下出现重复对的起始位置start,求得循环节长度len,就能确定第n个数
#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;

int a[52];
bool f[7][7];

int main()
{
    freopen("in.txt", "r", stdin);
    int A,B,n;
    int i,j,len;
    int start;
    while (cin >> A >> B >> n)
    {
        if (!A || !B || !n)
            break;
        for (i = 0; i < 7; i++)
            for (j = 0; j < 7; ++j)
                f[i][j]=false;
        a[1] = 1;
        a[2] = 1;
        f[1][1] = true;
        for (i = 3; i <= 100; ++i)
        {

            a[i] = (A*a[i-1]+B*a[i-2])%7;
            if (f[a[i-1]][a[i]])
            {
                for (j = 2; j < i; ++j)
                {
                    if ((a[j-1] == a[i-1]) && (a[j] == a[i]))
                    {
                        len = i - j;
                        start = j-2;
                        break;
                    }
                }
                break;
            }
            else
                f[a[i-1]][a[i]] = true;
        }
      //  cout << start << endl;
        if (n <= start)
            cout << a[n] << endl;
        else
        {
            if ((n - start)%len == 0)
                cout << a[1 + start] << endl;
            else
                cout << a[(n - start)%len + start] << endl;
        }

    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值