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