• 2020牛客寒假算法基础集训营1 J. 缪斯的影响力 (矩阵快速幂/费马小定理降幂)


    https://ac.nowcoder.com/acm/problem/200658

    f(n) = f(n-1) * f(n-2) * ab ,f的第一项是x,第二项是y。

    试着推出第三项是x·y·ab,第四项是x·y2·a2b,第五项是x2·y3·a4b,第六项是x3y5a7b

    可以发现x的指数成1 0 1 1 2 3,y的指数0 1 1 2 3 5,a的指数是0 0 b 2b 4b 7b。

    x和y的指数为斐波那契数列,a的指数规律为,除去系数b,其第n项前两项之和+1。

    由于数据范围很大,所以可以用矩阵快速幂求出x y a的指数的第n项是多少。

    x和y的乘法矩阵比较好构造

    1 1

    1 0

    对于b的乘法矩阵,因为f(n)= f(n-1)+ f(n-2)+ 1

    所以可以构造为:

    1 1 1

    1 0 0

    0 0 1

    因为最终是要求x·y·a的某次幂,且mod = 1e9+7是一个素数,所以这里再矩阵快速幂求解的过程中用费马小定理进行降幂操作

    因为ap-1≡1%p,所以ab%p = ab%(p-1)%p,在矩阵快速幂计算过程中矩阵元素相乘对mod-1取模而不是mod

    求出指数后,再用快速幂求解即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const ll mod = 1e9+7;
     5 struct Matrix {
     6   ll a[3][3];
     7   Matrix() { memset(a, 0, sizeof a); }
     8   Matrix operator*(const Matrix &b) const {//重载矩阵乘法
     9     Matrix res;
    10     for (int i = 0; i <= 2; ++i)
    11       for (int j = 0; j <= 2; ++j)
    12         for (int k = 0; k <= 2; ++k)
    13           res.a[i][j] = (res.a[i][j] + (a[i][k] * b.a[k][j] )%(mod-1) ) % (mod-1);
    14     return res;
    15   }
    16 }base1,base2,B,X,Y;
    17  
    18 void init(){
    19     base1.a[0][0] = base1.a[0][1] = base1.a[1][0] = 1;
    20     base2.a[0][0] = base2.a[0][1] = base2.a[0][2] = base2.a[1][0] = base2.a[2][2] = 1;
    21     B.a[2][0] = X.a[1][0] = Y.a[0][0] = 1;
    22 }
    23 Matrix qpow(Matrix a,ll n) {
    24   Matrix res;
    25   res.a[0][0] = res.a[1][1] = res.a[2][2] = 1;
    26   while (n) {
    27     if (n & 1) res = res * a;
    28     a = a * a;
    29     n >>= 1;
    30   }
    31   return res;
    32 }
    33 ll power(ll a,ll n){
    34     ll res=1;
    35     a = a % mod;
    36     while(n){
    37         if(n&1)res=res*a%mod;
    38         n>>=1;
    39         a=a*a% mod;
    40     }
    41     return res;
    42 }
    43  
    44 int main(){
    45     ll n,x,y,a,b;
    46     cin>>n>>x>>y>>a>>b;
    47     if(n == 1) {
    48         cout<<x%mod;
    49         return 0;
    50     }
    51     if(n == 2){
    52         cout<<y%mod;
    53         return 0;
    54     }
    55     if(x%mod==0||y%mod==0||a%mod==0){cout<<0;return 0;}
    56     x%=mod,y%=mod;
    57     init();
    58     Matrix b1 = qpow(base1,n-2);
    59     Matrix b2 = qpow(base2,n-2);
    60     X = b1*X,Y = b1*Y,B = b2*B;
    61     ll Cx = X.a[0][0],Cy = Y.a[0][0],Cb = B.a[0][0]; 
    62     a = power(a%mod,b);
    63     ll ans = ((power(x,Cx)*power(y,Cy)%mod)*power(a,Cb)%mod);
    64     cout<<ans;
    65     return 0;
    66 }
  • 相关阅读:
    链表 | 将递增有序的两个链表的公共元素合并为新的链表
    链表 | 将两个递增链表合并为一个递减链表
    雪花特效
    vuex笔记
    Vue路由
    Vue框架使用sass
    vue组件通信
    vue请求数据
    07_06.哈夫曼树
    07_05.通过链接实现二叉树及其遍历
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12266263.html
Copyright © 2020-2023  润新知