zoukankan      html  css  js  c++  java
  • [矩阵快速幂]HDOJ4565 So Easy!

    题意:给a, b, n, m 

    求 $left lceil ( a+ sqrt b )^n ight ceil$ % m

    看到 $( a+ sqrt b )^n$ 虽然很好联想到共轭 但是推出矩阵还是比较难的

        $(a+sqrt b)^n + (a-sqrt b)^n$

     = $(C^0_n a^n + C^1_n a^{n-1} sqrt{b} + ... + C^{n-1}_n a sqrt{b}^{n-1} + C^n_n (sqrt b)^n)$

        + $(C^0_n a^n + (-1)^1 C^1_n a^{n-1} sqrt{b} + ... + (-1)^{n-1} C^{n-1}_n a sqrt{b}^{n-1} + (-1)^n C^n_n sqrt b^{ n})$

    对于 n+1 项 $C^i_n$ 其中所有 i 为奇数的都消掉了 只剩下偶数项

     = $2 sumlimits_{i=0,i为偶数}^n C^i_n a {sqrt b}^{ i}$

    偶数 所以可以把根号开掉 得到

     = $2 sumlimits_{i=0}^{frac{n}{2}} C^i_n a {b}^{ i}$

    很明显这是一个整数

    数据范围为:$(a-1)^2 < b < a^2$

      那么    $a-1 < sqrt b < a$

      那么          $0 < a-sqrt b < 1$

    $(a+sqrt b)^n + (a-sqrt b)^n$ 是个整数 同时 $a-sqrt b$ 大于0 小于1 

    因此 $left lceil ( a+ sqrt b )^n ight ceil = (a+sqrt b)^n + (a-sqrt b)^n$  (画上这个等号真是不容易!)

    求 $(a+sqrt b)^n + (a-sqrt b)^n$ 就变得很简单了

    通过二次特征方程$x^2-2ax+(a^2-b)=0$

    可以得到$S_n = 2aS_{n-1}+(b-a^2)S_{n-2}$

    写成矩阵形式:

    $$egin{pmatrix} S_n\S_{n-1}end{pmatrix} = egin{pmatrix} a & {b-a^2}\ 1 & 0end{pmatrix} egin{pmatrix} S_{n-1}\S_{n-2}end{pmatrix}$$

    $$= {egin{pmatrix} a & {b-a^2}\ 1 & 0end{pmatrix}}^{n-1} egin{pmatrix} 2a \ 2 end{pmatrix}$$

    $b-a^2$ 很容易为负 n-1次方之后 更加负

    为了防止答案为负 记得多加几个mod哟~ 

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 LL mod;
     5 struct Mat
     6 {
     7     LL t[2][2];
     8 };
     9 Mat mul(Mat a, Mat b)
    10 {
    11     Mat c;
    12     memset(c.t, 0, sizeof(c.t));
    13     for(int i=0;i<2;i++)
    14         for(int k=0;k<2;k++)
    15             if(a.t[i][k])
    16                 for(int j=0;j<2;j++)
    17                     c.t[i][j]=(c.t[i][j]+a.t[i][k]*b.t[k][j])%mod;
    18     return c;
    19 }
    20 Mat expo(Mat p, LL k)
    21 {
    22     if(k==1)
    23         return p;
    24     Mat e;
    25     memset(e.t, 0, sizeof(e.t));
    26     for(int i=0;i<2;i++)
    27         e.t[i][i]=1;
    28     if(k==0)
    29         return e;
    30     while(k)
    31     {
    32         if(k & 1)
    33             e=mul(p, e);
    34         p=mul(p, p);
    35         k>>=1;
    36     }
    37     return e;
    38 }
    39 LL MOD(LL x)
    40 {
    41     while(x<0)
    42         x+=mod;
    43     return x%mod;
    44 }
    45 int main()
    46 {
    47 //freopen("in.txt", "r", stdin);
    48 //freopen("out.txt", "w", stdout);
    49     LL a, b, n;
    50     while(cin>>a>>b>>n>>mod)
    51     {
    52         Mat m;
    53         m.t[0][0]=2*a, m.t[0][1]=b-a*a;
    54         m.t[1][0]=1,   m.t[1][1]=0;
    55         Mat ans=expo(m, n-1);
    56         cout<<MOD(ans.t[0][0]*2*a+2*ans.t[0][1])<<endl;
    57     }
    58     return 0;
    59 }
    HDOJ 4565
  • 相关阅读:
    【转】Android WiFi 经常掉线出现的几个原因分析!
    如何分析解决Android ANR
    如何分析和研究Log文件 ,如何看日志信息
    Force removing ActivityRecord no saved state问题的原因分析
    win7下彻底卸载和重装mysql
    mysql的基本操作命令
    mysql 启动,停止,重启
    解决mysql登录报错ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)问题
    一个轻量级的基于 .NET Core 的 ORM 框架 HSQL
    C# ref引用参数与out输出参数的使用与区别
  • 原文地址:https://www.cnblogs.com/Empress/p/4509208.html
Copyright © 2011-2022 走看看