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)

  • 相关阅读:
    流程图
    如何撰写简历
    产品经理-visio
    关于 EF 对象的创建问题
    LINQ To EF
    IQueryable 与 IEnumberable 接口的区别
    UWP自动填充控件AutoSuggestBox小优化
    xamarin UWP证书问题汇总
    xamarin UWP中MessageDialog与ContentDialog的区别
    xamarin UWP自定义圆角按钮
  • 原文地址:https://www.cnblogs.com/aininot260/p/9569487.html
Copyright © 2011-2022 走看看