HDU-1005

题目描述:

 

解析:

emmm,n 挺大的,所以暴力应该是不能够解决的,然后是序列求解,想到得找序列规律、重复

根据递推公式:

f(n)=\left\{\begin{matrix} 1, & n=1\\ 1, & n=2\\ (A*f(n-1) + B*f(n-2))mod7, & n\geqslant 3 \end{matrix}\right.

n\geqslant 3 时,f(n) 取决于 f(n - 1) 和 f(n - 2) ,即,当序列中有两个数对(数对中两数相邻)相同时,由此数对开始至下一数对是一个循环节。

因为 f(n)\in \left \{ \left. 0,1,2,3,4,5,6 \right \} \right. ,则不同的数对最多有 49 对,故可以列举序列前 51 个数(共50对,必有重复数对),从中查找循环节。

  • 注:不一定是数对(1, 1)有可能前面部分序列不在循环中,而从中间某一处再开始循环

 

代码:

#include<stdio.h>

int seq[55];

int main()
{
    int a, b, n;
    while(scanf("%d%d%d", &a, &b, &n) && (a != 0 || b != 0 || n != 0)) // 判断是否 a = b = n = 0
    {
        // 生成序列的前 51 个
        seq[1] = seq[2] = 1;
        for(int i = 3; i < 52; i++)
            seq[i] = (a * seq[i - 1] + b * seq[i - 2]) % 7;

        // 找循环节
        int beg = 1;  // 开始循环的位置
        int cyc = 1;  // 循环周期
        bool flag = false;  // 是否找到循环节
        while(beg < 50 && !flag)
        {
            cyc = 1;
            while(cyc + beg < 51 && !flag)
            {
                if (seq[beg] == seq[beg + cyc] && seq[beg + 1] == seq[beg + cyc + 1])
                {
                    flag = true;
                    break;
                }
                cyc++;
            }
            beg++;
        }

        // 求 f(n)
        int ret; // 返回值

        if (n < beg + cyc)  // n 在第一个周期内或不在周期
            ret = seq[n];
        else  // n 不在第一个周期
        {
            int t = (beg - 1)+ (n - beg + 1) % cyc;
            ret = seq[t == 0 ? cyc : t];
            // 因为没有定义 seq[0]
            // (beg = 1 && n % cyc == 0)即 t == 0 时与 t != 0 时得分开讨论
        }

        printf("%d\n", ret);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值