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\n",ans); 160     return 0; 161 }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM