zoukankan      html  css  js  c++  java
  • E. Product Oriented Recurrence(矩阵快速幂+欧拉降幂)

    题目链接:

    https://codeforces.com/contest/1182/problem/E

    题目大意:

     f(x)=c^(2x6)f(x1)f(x2)f(x3)    for x4x≥4.

    给你f1,f2,f3,n,c。求第n项的结果。

    具体思路:

    看到递推式想到用矩阵快速幂优化;但是如果都是乘法的话,是无法化成矩阵相乘的形式的。然后就开始想怎么将乘法转换成加法。推了一个多小时也没有推出来。。

    具体的解题过程如下:

    对于每一项,这一项里面包含的f1 和 f2 和 f3 和 c 的 个数都是能由它前面的能通过加法的形式实现的,最终结果再将这些乘起来就好了。

    第i项中f1的个数 = 第i-1项中f1的个数+第i-2项中f1的个数+第i-3项中f1的个数;

    f2,f3同理。

    第i项中c的个数 = 第i-1项中c的个数 + 第i-2项中c的个数 + 第i-3项中c的个数 + 2*i - 6;

    (g[i],g[i-1],g[i-2])=(g[i-1],g[i-2],g[i-3])*

    [1 1 0

    1 0 1

    1 0 0   ].

    (f[i],f[i-1],f[i-2],g[i-3],i,1) = (f[i-1],f[i-2],f[i-3],i-1,1)*

    [ 1 1 0 0 0

      1 0 1 0 0   

      1 0 0 0 0 

      2 0 0 1 0

      -4 0 0 1 1

    ]

    注意这里的矩阵最终解出的结果是指数,也就是说模数并不是1e9+7.而应该是phi(1e9+7)=1e9+6.

    AC代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn = 2e6+20;
      4 # define ll long long
      5 # define inf 0x3f3f3f3f
      6 const ll mod = 1e9+6;
      7 ll MD=mod+1;
      8 ll phi(ll x)
      9 {
     10     ll res=x,a=x;
     11     for(ll i=2; i*i<=x; i++)
     12     {
     13         if(a%i==0)
     14         {
     15             res=res/i*(i-1ll);
     16             while(a%i==0)
     17                 a/=i;
     18         }
     19     }
     20     if(a>1ll)
     21         res=res/a*(a-1ll);
     22     return res;
     23 }
     24 struct Matrix_First
     25 {
     26     ll a[5][5];
     27     Matrix_First operator *(Matrix_First b)
     28     {
     29         Matrix_First tmp;
     30         for(int i=1; i<=3; i++)
     31         {
     32             for(int j=1; j<=3; j++)
     33             {
     34                 tmp.a[i][j]=0;
     35                 for(int k=1; k<=3; k++)
     36                 {
     37                     tmp.a[i][j]=(tmp.a[i][j]+a[i][k]*b.a[k][j]%mod)%mod;
     38                     while(tmp.a[i][j]<0)
     39                         tmp.a[i][j]+=mod;// 这是求指数的过程
     40                     tmp.a[i][j]%=mod;
     41                 }
     42             }
     43         }
     44         return tmp;
     45     }
     46 } g1,g2,g3;
     47 struct Matrix_Second
     48 {
     49     ll a[6][6];
     50     Matrix_Second operator *(Matrix_Second b)
     51     {
     52         Matrix_Second tmp;
     53         for(int i=1; i<=5; i++)
     54         {
     55             for(int j=1; j<=5; j++)
     56             {
     57                 tmp.a[i][j]=0;
     58                 for(int k=1; k<=5; k++)
     59                 {
     60                     tmp.a[i][j]=(tmp.a[i][j]+a[i][k]*b.a[k][j]%mod)%mod;
     61                     while(tmp.a[i][j]<mod)
     62                         tmp.a[i][j]+=mod;
     63                     tmp.a[i][j]%=mod;
     64                 }
     65             }
     66         }
     67         return tmp;
     68     }
     69 } f;
     70 
     71 Matrix_First qsm_First(Matrix_First t1,ll t2)
     72 {
     73     Matrix_First  ans=t1;
     74     t2--;
     75     while(t2)
     76     {
     77         if(t2&1)
     78             ans=ans*t1;
     79         t1=t1*t1;
     80         t2>>=1;
     81     }
     82     return ans;
     83 }
     84 
     85 Matrix_Second qsm_Second(Matrix_Second t1,ll t2)
     86 {
     87     Matrix_Second  ans=t1;
     88     t2--;
     89     while(t2)
     90     {
     91         if(t2&1)
     92             ans=ans*t1;
     93         t1=t1*t1;
     94         t2>>=1;
     95     }
     96     return ans;
     97 }
     98 
     99 ll qsm(ll t1,ll t2)
    100 {
    101     ll ans=1ll;
    102     while(t2)
    103     {
    104         if(t2&1)
    105             ans=ans*t1%MD;
    106         t1=t1*t1%MD;
    107         t2>>=1;
    108     }
    109     return ans;
    110 }
    111 int main()
    112 {
    113     ll n,f1,f2,f3,c;
    114     scanf("%lld %lld %lld %lld %lld",&n,&f1,&f2,&f3,&c);
    115     g1.a[1][1]=1;g1.a[1][2]=1;g1.a[1][3]=0;
    116     g1.a[2][1]=1;g1.a[2][2]=0;g1.a[2][3]=1;
    117     g1.a[3][1]=1;g1.a[3][2]=0;g1.a[3][3]=0;
    118 
    119     g2.a[1][1]=1;g2.a[1][2]=1;g2.a[1][3]=0;
    120     g2.a[2][1]=1;g2.a[2][2]=0;g2.a[2][3]=1;
    121     g2.a[3][1]=1;g2.a[3][2]=0;g2.a[3][3]=0;
    122 
    123     g3.a[1][1]=1;g3.a[1][2]=1;g3.a[1][3]=0;
    124     g3.a[2][1]=1;g3.a[2][2]=0;g3.a[2][3]=1;
    125     g3.a[3][1]=1;g3.a[3][2]=0;g3.a[3][3]=0;
    126     g1=qsm_First(g1,(n-3ll));
    127     g2=qsm_First(g2,(n-3ll));
    128     g3=qsm_First(g3,(n-3ll));
    129 
    130     ll num_1=g1.a[3][1];
    131     ll num_2=g2.a[2][1];
    132     ll num_3=g3.a[1][1];
    133     f.a[1][1]=1;f.a[1][2]=1;f.a[1][3]=0;f.a[1][4]=0;f.a[1][5]=0;
    134     f.a[2][1]=1;f.a[2][2]=0;f.a[2][3]=1;f.a[2][4]=0;f.a[2][5]=0;
    135     f.a[3][1]=1;f.a[3][2]=0;f.a[3][3]=0;f.a[3][4]=0;f.a[3][5]=0;
    136     f.a[4][1]=2;f.a[4][2]=0;f.a[4][3]=0;f.a[4][4]=1;f.a[4][5]=0;
    137     f.a[5][1]=-4;f.a[5][2]=0;f.a[5][3]=0;f.a[5][4]=1;f.a[5][5]=1;
    138     f=qsm_Second(f,n-3ll);
    139     ll num_c=(3ll*f.a[4][1]+f.a[5][1]);
    140     while(num_c<0)
    141         num_c+=mod;
    142     num_c%=mod;
    143 
    144     ll ans=qsm(f1,num_1)%MD*qsm(f2,num_2)%MD;
    145    // cout<<ans<<endl;
    146     while(ans<0)
    147         ans+=MD;
    148     ans%=MD;
    149     ans=ans*qsm(f3,num_3)%MD;
    150    // cout<<ans<<endl;
    151     while(ans<0)
    152         ans+=MD;
    153     ans%=MD;
    154     ans=ans*qsm(c,num_c)%MD;
    155    // cout<<ans<<endl;
    156     while(ans<0)
    157         ans+=MD;
    158     ans%=MD;
    159     printf("%lld
    ",ans);
    160     return 0;
    161 }
  • 相关阅读:
    Digital Square(hdu4394)搜索
    Substrings(hdu1238)字符串匹配
    Graveyard(poj3154)
    数据库的范式理论
    模和除
    You can Solve a Geometry Problem too (hdu1086)几何,判断两线段相交
    对vector等STL标准容器进行排序操作(转!)
    0 or 1(hdu2608)数学题
    LintCode 4.丑数
    LintCode 9.Fizz Buzz问题
  • 原文地址:https://www.cnblogs.com/letlifestop/p/11011697.html
Copyright © 2011-2022 走看看