zoukankan      html  css  js  c++  java
  • 数学:广义斐波纳契数列循环节

    我们定义一个f(n)函数,f(n) = a * f(n - 1) + b * f(n - 2), f(1) = c, f(2) = d.
    问f(n)在模1000000007情况下的最小循环节。即求最小的m,使对任意的n有f(n) % 1000000007 = f(n + m) % 1000000007

    这个题目不仅交不了,而且我还没办法验证代码的正确性,我还没办法

    所以这里仅仅贴一份广义斐波纳契的代码,希望它是对的吧

      1 #include <iostream>
      2 #include <cstring>
      3 #include <algorithm>
      4 #include <cstdio>
      5 #include <cmath>
      6 using namespace std;
      7 typedef long long LL;
      8 const int N = 2;
      9 const LL MOD = 1000000007;
     10 
     11 LL fac[2][505];
     12 int cnt,ct;
     13 
     14 LL pri[6] = {2, 3, 7, 109, 167, 500000003};
     15 LL num[6] = {4, 2, 1, 2, 1, 1};
     16 
     17 struct Matrix
     18 {
     19     LL m[N][N];
     20 } ;
     21 
     22 Matrix A;
     23 Matrix I = {1, 0, 0, 1};
     24 
     25 Matrix multi(Matrix a,Matrix b)
     26 {
     27     Matrix c;
     28     for(int i=0; i<N; i++)
     29     {
     30         for(int j=0; j<N; j++)
     31         {
     32             c.m[i][j]  =0;
     33             for(int k=0; k<N; k++)
     34             {
     35                 c.m[i][j] += a.m[i][k] * b.m[k][j];
     36                 c.m[i][j] %= MOD;
     37             }
     38         }
     39     }
     40     return c;
     41 }
     42 
     43 Matrix power(Matrix A,LL n)
     44 {
     45     Matrix ans = I, p = A;
     46     while(n)
     47     {
     48         if(n & 1)
     49         {
     50             ans = multi(ans,p);
     51             n--;
     52         }
     53         n >>= 1;
     54         p = multi(p,p);
     55     }
     56     return ans;
     57 }
     58 
     59 LL quick_mod(LL a,LL b)
     60 {
     61     LL ans = 1;
     62     a %= MOD;
     63     while(b)
     64     {
     65         if(b & 1)
     66         {
     67             ans = ans * a % MOD;
     68             b--;
     69         }
     70         b >>= 1;
     71         a = a * a % MOD;
     72     }
     73     return ans;
     74 }
     75 
     76 LL Legendre(LL a,LL p)
     77 {
     78     LL t = quick_mod(a,(p-1)>>1);
     79     if(t == 1) return 1;
     80     return -1;
     81 }
     82 
     83 void dfs(int dept,LL product = 1)
     84 {
     85     if(dept == cnt)
     86     {
     87         fac[1][ct++] = product;
     88         return;
     89     }
     90     for(int i=0; i<=num[dept]; i++)
     91     {
     92         dfs(dept+1,product);
     93         product *= pri[dept];
     94     }
     95 }
     96 
     97 bool OK(Matrix A,LL n)
     98 {
     99     Matrix ans = power(A,n);
    100     return ans.m[0][0] == 1 && ans.m[0][1] == 0 &&
    101            ans.m[1][0] == 0 && ans.m[1][1] == 1;
    102 }
    103 
    104 int main()
    105 {
    106     fac[0][0] = 1;
    107     fac[0][1] = 2;
    108     fac[0][2] = 500000003;
    109     fac[0][3] = 1000000006;
    110     LL a,b,c,d;
    111     while(cin>>a>>b>>c>>d)
    112     {
    113         LL t = a * a + 4 * b;
    114         A.m[0][0] = a;
    115         A.m[0][1] = b;
    116         A.m[1][0] = 1;
    117         A.m[1][1] = 0;
    118         if(Legendre(t,MOD) == 1)
    119         {
    120             for(int i=0; i<4; i++)
    121             {
    122                 if(OK(A,fac[0][i]))
    123                 {
    124                     cout<<fac[0][i]<<endl;
    125                     break;
    126                 }
    127             }
    128         }
    129         else
    130         {
    131             ct = 0;
    132             cnt = 6;
    133             dfs(0,1);
    134             sort(fac[1],fac[1]+ct);
    135             for(int i=0;i<ct;i++)
    136             {
    137                 if(OK(A,fac[1][i]))
    138                 {
    139                     cout<<fac[1][i]<<endl;
    140                     break;
    141                 }
    142             }
    143         }
    144     }
    145     return 0;
    146 }

    当然,要附上博主的链接,做这个题的时候的玄学的数学方法,可能这辈子都不会再用到了

    https://blog.csdn.net/ACdreamers/article/details/25616461

    当然不能就这么算了,普通的斐波纳契数列求其模除一个数的循环节的题还是好找的

    HDU3977

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 int res;
      6 int factor[33][2];
      7 long long len[1000005];
      8 struct Mat
      9 {
     10     long long mat[3][3];
     11     int row,col;
     12 };
     13 long long gcd(long long a,long long b)
     14 {
     15     return b==0?a:gcd(b,a%b);
     16 }
     17 long long lcm(long long a,long long b)
     18 {
     19     return a/gcd(a,b)*b;
     20 }
     21 Mat mod_mul(Mat a,Mat b,long long p)
     22 {
     23     Mat ans;
     24     ans.row=a.row;
     25     ans.col=b.col;
     26     memset(ans.mat,0,sizeof(ans.mat));
     27     for(int i=0;i<ans.row;i++)
     28         for(int k=0;k<a.col;k++)
     29             if(a.mat[i][k])
     30                 for(int j=0;j<ans.col;j++)
     31                 {
     32                     ans.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
     33                     ans.mat[i][j]%=p;
     34                 }
     35     return ans;
     36 }
     37 Mat mod_pow(Mat a,long long k,long long p)
     38 {
     39     Mat ans;
     40     ans.row=a.row;
     41     ans.col=a.col;
     42     for(int i=0;i<a.row;i++)
     43         for(int j=0;j<a.col;j++)
     44             ans.mat[i][j]=(i==j);
     45     while(k)
     46     {
     47         if(k&1) ans=mod_mul(ans,a,p);
     48         a=mod_mul(a,a,p);
     49         k>>=1;
     50     }
     51     return ans;
     52 }
     53 long long deal(int x)
     54 {
     55     if(len[x]!=-1) return len[x];
     56     Mat A;
     57     A.mat[0][0]=A.mat[0][1]=A.mat[1][0]=1,A.mat[1][1]=0;
     58     A.row=A.col=2;
     59     long long p=1ll*(x-1)*(x+1);
     60     long long ans=p;
     61     for(long long i=2;i*i<p;i++)
     62         if(p%i==0)
     63         {
     64             Mat B=mod_pow(A,i,x);
     65             if(B.mat[0][0]==1&&B.mat[0][1]==0)
     66             if(B.mat[1][0]==0&&B.mat[1][1]==1)
     67                 ans=min(ans,i);
     68             B=mod_pow(A,p/i,x);
     69             if(B.mat[0][0]==1&&B.mat[0][1]==0)
     70             if(B.mat[1][0]==0&&B.mat[1][1]==1)
     71                 ans=min(ans,p/i);
     72         }
     73     return len[x]=ans;
     74 }
     75 void get_factor(int p)
     76 {
     77     res=0;
     78     for(int i=2;i*i<=p;i++)
     79         if(p%i==0)
     80         {
     81             factor[res][0]=i,factor[res][1]=0;
     82             while(p%i==0) p/=i,factor[res][1]++;
     83             res++;
     84         }
     85     if(p>1) factor[res][0]=p,factor[res++][1]=1;
     86 }
     87 int main()
     88 {
     89     memset(len,-1,sizeof(len));
     90     len[1]=1,len[2]=3,len[3]=8,len[4]=6,len[5]=20;
     91     int T,p,cas=1;
     92     scanf("%d",&T);
     93     while(T--)
     94     {
     95         scanf("%d",&p);
     96         get_factor(p);
     97         long long ans=1;
     98         for(int i=0;i<res;i++)
     99         {
    100             long long tmp=deal(factor[i][0]);
    101             for(int j=1;j<factor[i][1];j++) tmp*=factor[i][0];
    102             ans=lcm(ans,tmp);
    103         }
    104         printf("Case #%d: %lld
    ",cas++,ans);
    105     }
    106 }

    这个坑等数学学好了再滚回来填(可能数学学不好了QAQ)

  • 相关阅读:
    Atitit attilax要工作研究的要素 纪要 方案 趋势 方向 概念 理论
    Atitit 常见每日流程日程日常工作.docx v7 r8f
    Atitit it 互联网 软件牛人的博客列表
    Atitit 信息链(Information Chain)的概念理解 attilax总结
    Atitit 知识点的体系化 框架与方法 如何了解 看待xxx
    Atitit 聚合搜索多个微博 attilax总结
    Atitit 企业知识管理PKM与PIM
    Atitit 项目沟通管理 Atitit 沟通之道 attilax著.docx
    Atitit 项目管理软件 在线服务 attilax总结 1. 项目管理协作的历史 1 1.1. Worktile 406k 1 1.2. Teambition  584k in baidu
    Atitit.每周末总结 于每周一计划日程表 流程表 v8 import 上周遗漏日志补充 检查话费 检查流量情况 Crm问候 Crm表total and 问候
  • 原文地址:https://www.cnblogs.com/aininot260/p/9569487.html
Copyright © 2011-2022 走看看