hdu 1005 Number Sequence

清疚 2021-10-13 01:59 375阅读 0赞

hdu 1005 Number Sequence

  • 题意
  • 题解
  • 源代码

传送门

题意

  1. 现有有这样的一个递推式:
  2. f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.
  3. 给定AB,n,求解fn

题解

  1. 由于n过大,如果直接线性O(n)求解可能会超时,所以需要从递推式中找到关系,
  2. 易知f(n)需要对7进行取模,所以f(n)比较小,可知,f(n)在较小的范围就会循环,当
  3. 连续的两个数在前面出现过,将会产生循环,所以这题需要找到循环节,f(n)<6,可以
  4. 利用f(n-1)*10+f(n)作为一个标记,记录在序列出现的位置,当求解的时候,遇到时
  5. 就退出循环,根据关系式直接求解f(n)即可

源代码

  1. #include<iostream>
  2. using namespace std;
  3. const int maxn = 67;
  4. int main(){
  5. std::ios::sync_with_stdio(false);
  6. cin.tie(0);
  7. cout.tie(0);
  8. int a,b,n,c[maxn]={ 0,1,1},d[maxn];
  9. //c 代表需要求解的序列
  10. //d 标记f(n-1)*10+f(n)出现的位置,初始为0,代表为出现
  11. while (cin>>a>>b>>n&&(a+b+n))
  12. {
  13. a%=7;
  14. b%=7;
  15. for(int i=0;i<maxn;++i)d[i]=0;
  16. d[11]=1;
  17. int i,j;
  18. for(i=3;i<=n;++i){
  19. c[i]=(c[i-1]*a+c[i-2]*b)%7;
  20. j = c[i-1]*10+c[i];
  21. if(d[j])break;//前面求解过,循环的地方
  22. d[j]=i-1;
  23. }
  24. if(n>=i)if(n>=i)n=(n-d[j])%(i-1-d[j])+d[j];
  25. // n - d[j]:n与循环开始的距离
  26. // i-1-d[j]:循环节的长度
  27. // +d[j]:加上循环初始的初始位置
  28. cout<<c[n]<<"\n";
  29. }
  30. }

发表评论

表情:
评论列表 (有 0 条评论,375人围观)

还没有评论,来说两句吧...

相关阅读