• UVA10655 Contemplation! Algebra —— 推公式、矩阵快速幂


    题目链接:https://vjudge.net/problem/UVA-10655

    题意:

    a+b、ab的值分别为p、q,求a^n+b^n。

    题解:

    1.a、b未知,且直接求出a、b也不太实际。

    2.看到 a^n+b^n 这个式子就想到二阶齐次递推式的通项公式,然后就想是否能通过通项公式反推回递推式。结果发现a、b的值是不能确定是否相等的,而求二阶齐次递推式的通项公式时,是需要根据根的情况来分类求解的,所以此题不适应。

    3.那么,就直接对 a^n+b^n 做一下变形:

    4.得到递推式之后,就直接构造矩阵,然后快速幂。

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <cmath>
     7 #include <queue>
     8 #include <stack>
     9 #include <map>
    10 #include <string>
    11 #include <set>
    12 using namespace std;
    13 typedef long long LL;
    14 const int INF = 2e9;
    15 const LL LNF = 9e18;
    16 const int MOD = 1e9+7;
    17 const int MAXN = 1e6+100;
    18 
    19 const int Size = 2;
    20 struct MA
    21 {
    22     LL mat[Size][Size];
    23     void init()
    24     {
    25         for(int i = 0; i<Size; i++)
    26         for(int j = 0; j<Size; j++)
    27             mat[i][j] = (i==j);
    28     }
    29 };
    30 
    31 MA mul(MA x, MA y)
    32 {
    33     MA ret;
    34     memset(ret.mat, 0, sizeof(ret.mat));
    35     for(int i = 0; i<Size; i++)
    36     for(int j = 0; j<Size; j++)
    37     for(int k = 0; k<Size; k++)
    38         ret.mat[i][j] += 1LL*x.mat[i][k]*y.mat[k][j];
    39     return ret;
    40 }
    41 
    42 MA qpow(MA x, LL y)
    43 {
    44     MA s;
    45     s.init();
    46     while(y)
    47     {
    48         if(y&1) s = mul(s, x);
    49         x = mul(x, x);
    50         y >>= 1;
    51     }
    52     return s;
    53 }
    54 
    55 
    56 int main()
    57 {
    58     LL p, q, n, f[2];
    59     while(scanf("%lld%lld%lld", &p,&q,&n)==3)
    60     {
    61         f[0] = 2; f[1] = p;
    62         if(n<=1)
    63         {
    64             printf("%lld
    ", f[n]);
    65             continue;
    66         }
    67 
    68         MA s;
    69         memset(s.mat, 0, sizeof(s.mat));
    70         s.mat[0][0] = p; s.mat[0][1] = -q;
    71         s.mat[1][0] = 1; s.mat[1][1] = 0;
    72 
    73         s = qpow(s, n-1);
    74         LL ans = 1LL*s.mat[0][0]*f[1] + 1LL*s.mat[0][1]*f[0];
    75         printf("%lld
    ", ans);
    76     }
    77 }
    View Code
  • 相关阅读:
    GTK+中的树状列表构件(GtkTreeView)
    [TOP]疯狂的投资
    多线程模式之MasterWorker模式
    一年读书总结
    Microsoft Visual Studio正忙解决办法
    使用vs自带的性能诊断工具
    C#中的扩展方法
    从委托、匿名方法到Lambda
    c#中的事件
    sqlserver中创建包含事务的存储过程
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8426209.html
Copyright © 2020-2023  润新知