• Fibonacci数列的幂和 zoj 3774


    题目大意:

    求斐波那契数列前n项的k次幂和  Mod 1000000009。    n<=1e18, k<=1e5

     


     

    这题的k比较大,所以不能用矩阵乘法来递推。学到了新姿势...  http://blog.csdn.net/acdreamers/article/details/23039571

     

    基本思想就是求出通项公式,把里面的$sqrt{5}$   用 $x$ 代替, 其中 $x^2equiv 5pmod{1000000009}$

    然后二项式展开求和就好了。

    一个合法的$x$是383008016。 正好前几天做了个高次剩余方程的题,直接拉过去跑出来。。

    为什么这样替代是合法的呢? 网络上好像没找到严谨的证明。

    下面给出我个人的不严谨证明:

    将原式子合并之后最终会得到$frac{P(t)}{Q(t)}$ 这样的形式。 其中$t=sqrt{5}$  $P(t)$和$Q(t)$是关于$t$的多项式.

    把$P(t)$ $Q(t)$中次数>=2的可以利用$t^2=5$降幂成次数不超过1的, 最后变成$frac{P'(t)}{Q'(t)}$ 这样的形式.

    由于最终答案一定是整数,所以 $Q'(t)$ 能整除  $P'(t)$ 。      设 $frac{P'(t)}{Q'(t)}=K$

    那么把$t$ 换成 上面求出的 $x$  得到的 $frac{P'(x)}{Q'(x)}$ 也是 $K$. 不影响答案。

    AC代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 #include <vector>
     7 #include <map>
     8 #include <cstdlib>
     9 #include <set>
    10 #include <queue>
    11 using namespace std;
    12 
    13 #define X first
    14 #define Y second
    15 #define Mod 1000000009
    16 #define N 100010
    17 #define M 101
    18 
    19 typedef long long ll;
    20 
    21 const int INF=1<<30;
    22 const int sqrt5=383008016;
    23 int P,Q;
    24 int fac[N],fac_inv[N];
    25 
    26 int Power(int x,ll p)
    27 {
    28     int res=1;
    29     for (;p;p>>=1)
    30     {
    31         if (p&1) res=1ll*res*x%Mod;
    32         x=1ll*x*x%Mod;
    33     }
    34     return res;
    35 }
    36 
    37 int C(int n,int m)
    38 {
    39     if (m==0) return 1;
    40     int res=1ll*fac[n]*fac_inv[m]%Mod;
    41     return 1ll*res*fac_inv[n-m]%Mod;
    42 }
    43 
    44 int main()
    45 {
    46     //freopen("in.in","r",stdin);
    47     //freopen("out.out","w",stdout);
    48     
    49     P=1ll*(1+sqrt5)*Power(2,Mod-2)%Mod;
    50     Q=1ll*(1-sqrt5)*Power(2,Mod-2)%Mod;
    51     if (Q<0) Q+=Mod;
    52     fac[0]=fac_inv[0]=1;
    53     for (int i=1;i<N;i++) fac[i]=1ll*fac[i-1]*i%Mod,fac_inv[i]=Power(fac[i],Mod-2);
    54     int T,K,ans; ll n;  
    55     scanf("%d",&T);
    56     while (T--)
    57     {
    58         scanf("%lld%d",&n,&K);
    59         ans=0;
    60         for (int i=K,op=1;i>=0;i--,op=-op)
    61         {
    62             int tmp1=op*C(K,i),tmp2,x=1ll*Power(P,i)*Power(Q,K-i)%Mod;
    63             if (x==1) tmp2=n%Mod;
    64             else tmp2=1ll*x*(Power(x,n)-1)%Mod,tmp2=1ll*tmp2*Power(x-1,Mod-2)%Mod;
    65             ans+=1ll*tmp1*tmp2%Mod;
    66             ans%=Mod;
    67         }
    68         if (ans<0) ans+=Mod;
    69         ans=1ll*ans*Power(Power(sqrt5,Mod-2),K)%Mod;
    70         printf("%d
    ",ans);
    71     }
    72     return 0;
    73 }
    View Code

    我的求高次剩余方程的代码(目前只会做模数是质数的情况...): 

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1038

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <queue>
      4 #include <cmath>
      5 #include <map>
      6 #include <algorithm>
      7 #include <cstring>
      8 #include <set>
      9 using namespace std;
     10 
     11 
     12 #define X first
     13 #define Y second
     14 #define N 100010
     15 #define M 5783
     16 typedef long long ll;
     17 typedef unsigned long long ull;
     18 
     19 const int Mod=1000000007;
     20 
     21 int prime[N];
     22 bool flag[N];
     23 vector<int> ans;
     24 
     25 int Power(int x,int p,int Mod)
     26 {
     27     int res=1;
     28     for (;p;p>>=1)
     29     {
     30         if (p&1) res=1ll*res*x%Mod;
     31         x=1ll*x*x%Mod;
     32     }
     33     return res;
     34 }
     35 
     36 bool Check(int g,int P,int a[])
     37 {
     38     for (int i=1;i<=a[0];i++) if (Power(g,(P-1)/a[i],P)==1) return false;
     39     return true;
     40 }
     41 
     42 int Find_Root(int P)
     43 {
     44     int x=P-1,a[100]; a[0]=0;
     45     for (int i=1;i<=prime[0] && prime[i]*prime[i]<=x;i++)
     46     {
     47         if (x%prime[i]==0)
     48         {
     49             a[++a[0]]=prime[i];
     50             while (x%prime[i]==0) x/=prime[i];
     51         }
     52     }
     53     if (x!=1) a[++a[0]]=x;
     54     for (int i=2;;i++) if (Check(i,P,a)) return i;
     55 }
     56 
     57 vector<pair<int,int> > hash[M];
     58 
     59 int Calc_Exp(int a,int b,int P)  // 求解a^x=b (mod P)
     60 {
     61     int m=ceil(sqrt(P+0.5)); 
     62     for (int i=0;i<M;i++) hash[i].clear();
     63     
     64     int v=Power(a,m,P),tmp=1; v=Power(v,P-2,P);
     65     hash[1].push_back(make_pair(1,0));
     66     for (int i=1;i<m;i++) 
     67     {
     68         tmp=1ll*tmp*a%P;
     69         hash[tmp%M].push_back(make_pair(tmp,i));
     70     }
     71     
     72     for (int i=0;i<m;i++)
     73     {
     74         int t=b%M;
     75         for (int j=0;j<hash[t].size();j++)
     76         {
     77             if (hash[t][j].X==b) return i*m+hash[t][j].Y;
     78         }
     79         b=1ll*b*v%P;
     80     }
     81 }
     82 
     83 void ex_gcd(ll a,ll b,ll &x,ll &y,ll &d)
     84 {
     85     if (!b)
     86     {
     87         d=a;
     88         x=1;
     89         y=0;
     90     }
     91     else
     92     {
     93         ex_gcd(b,a%b,y,x,d);
     94         y-=a/b*x;
     95     }
     96 }
     97 
     98 //X^A = B (mod P)
     99 void Solve_Equation(int A,int B,int P)
    100 {
    101     ans.clear();
    102     int g=Find_Root(P); //求出P的原根 
    103     int b=Calc_Exp(g,B,P);  // B=g^b
    104     ll x,y,d;
    105     ex_gcd(A,P-1,x,y,d);
    106     if (b%d==0)
    107     {
    108         int del=(P-1)/d,tmp,t;
    109         x*=b/d;
    110         x%=del;
    111         if (x<0) x+=del;
    112         tmp=Power(g,(int)x,P);
    113         t=Power(g,del,P);
    114         while (x<=P-2) ans.push_back(tmp),x+=del,tmp=1ll*tmp*t%P;
    115         sort(ans.begin(),ans.end());
    116         for (int i=0;i<ans.size();i++) printf("%d%c",ans[i],i==ans.size()-1? '
    ':' ');
    117     }
    118     if (ans.size()==0) printf("No Solution
    ");
    119 }
    120 
    121 int main()
    122 {
    123     //freopen("in.in","r",stdin);
    124     //freopen("out.out","w",stdout);
    125     
    126     for (int i=2;i<N;i++)
    127     {
    128         if (!flag[i]) prime[++prime[0]]=i;
    129         for (int j=1;j<=prime[0] && i*prime[j]<N;j++)
    130         {
    131             flag[i*prime[j]]=true;
    132             if (i%prime[j]==0) break;
    133         }
    134     }
    135     
    136     int T,A,B,P; scanf("%d",&T);
    137     while (T--)
    138     {
    139         scanf("%d%d%d",&P,&A,&B);
    140         Solve_Equation(A,B,P);
    141     }
    142     
    143     return 0;
    144 }
    View Code

    可以扩展到模数不是质数的情况,等我学会了在写篇文章 记录具体做法吧。

  • 相关阅读:
    【转】Android系统中Fastboot和Recovery所扮演的角色。
    【转】Android ROM分析(1):刷机原理及方法
    【转】ANDROIDROM制作(一)——ROM结构介绍、精简和内置、一般刷机过程
    【转】使用fastboot命令刷机流程详解
    检测是否安装或者开启flash
    CentOS中/英文环境切换教程(CentOS6.8)
    id: cannot find name for user ID xxx处理办法
    linux重命名所有find查找到的文件/文件夹
    linux过滤旧文件中的空行和注释行剩余内容组成新文件
    CentOS和AIX查看系统序列号
  • 原文地址:https://www.cnblogs.com/vb4896/p/6545602.html
Copyright © 2020-2023  润新知