E. Product Oriented Recurrence(矩阵快速幂+欧拉降幂)
题目链接:
https://codeforces.com/contest/1182/problem/E
题目大意:
f(x)=c^(2x−6)⋅f(x−1)⋅f(x−2)⋅f(x−3) for x≥4x≥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 }