Number Sequence (HDOJ 1005)

本文深入解析HDOJ中一道难题的高效求解策略,通过分析f(n)=(A*f(n-1)+B*f(n-2))mod7的周期特性,避免超时问题。阐述了如何利用模运算和数组存储技巧,找到序列周期,快速计算大规模数据下的f(n)值。

题目分析:由于n的范围在1~100,000,000,所以利用常规的每次保存上次运算结果的方法绝对会超时。题中mod7,即为解题的突破口,

          由于mod 7 所以f(n)的值只可能有7种结果(0~6),另由f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.,其中

                        A * f(n - 1) + B * f(n - 2)的结果所构成的序列的周期最多不过49,因为由排列组合的原理,

                        f(n-1) 7中结果,f(n-2) 7种结果,可得共49种变化。

                        到此解题就顺理成章了,把每个结果保存在数组中,直到发现数组的值又变回f(n)=1,f(n-1)=1;时,即为数组序列的周期。得到周期i后,最后的f(n)即等于f[n%i]

实现代码:

 

ContractedBlock.gifExpandedBlockStart.gifCode
 1#include <vector>
 2#include "stdio.h"
 3#include "iostream.h"
 4
 5
 6int main()
 7ExpandedBlockStart.gifContractedBlock.gif{
 8    long n;
 9    int A,B,f[200];
10    while(scanf("%d %d %ld",&A,&B,&n)!=EOF&&A&&B&&n)
11ExpandedSubBlockStart.gifContractedSubBlock.gif    {
12        for(int j=0;j<200;j++)
13ExpandedSubBlockStart.gifContractedSubBlock.gif        {
14            f[j]=0;
15        }

16        if(n==1||n==2)    
17            cout<<1<<endl;
18        else
19ExpandedSubBlockStart.gifContractedSubBlock.gif        {
20            long i;
21            f[1]=1;
22            f[2]=1;
23            for(i=3;i<200;i++)
24ExpandedSubBlockStart.gifContractedSubBlock.gif            {
25                f[i]=(A*f[i-1]+B*f[i-2])%7;
26                if(f[i]==1&&f[i-1]==1)
27                    break;
28            }

29            i=i-2;
30            f[0]=f[i];
31            cout<<f[n%i]<<endl;
32        }

33    }

34    return 0
35}

36

 

讨论:在本题AC之后,忽在网上发现了这种解法其实是错误的,因为这个循环的结果序列不一定从第一个开始,所以随着测试数据的增强,定会碰到错误情况,但可能由于HDOJ的测试数据不够强,让我侥幸过关~~~。解决方案是,为所得到的结果序列增加一个标示,当重复出现两次得到同样的序列后,即可确定所得的序列周期即为正确的。

 

转载于:https://www.cnblogs.com/SoYoung/archive/2009/04/19/1439058.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值