cf|Codeforces1182E Product Oriented Recurrence(递推+矩乘快速幂)

题目链接
这道题是道好题
给定柿子 f x = c 2 x ? 6 ? f x ? 1 ? f x ? 2 ? f x ? 3  c , f x ? 1 , f x ? 2 , f x ? 3 f_{x} = c^{2x-6} \cdot f_{x-1} \cdot f_{x-2} \cdot f_{x-3}\ \ \,c, f_{x-1} , f_{x-2}, f_{x-3} fx?=c2x?6?fx?1??fx?2??fx?3?c,fx?1?,fx?2?,fx?3?已知
求 f n , n ≤ 1 0 9 f{_n},n\le10^{9} fn?,n≤109
这题一看就是矩阵快速幂…考虑怎么构造
传统的矩阵乘法只资瓷前n项相加的形式。考虑变形,发现我们可以变成
f x ? c x = c x ? 1 ? f x ? 1 ? c x ? 2 ? f x ? 2 ? c x ? 3 ? f x ? 3 f_{x} \cdot c^{x}= c^{x-1} \cdot f_{x-1} \cdot c^{x-2} \cdot f_{x-2} \cdot c^{x-3} \cdot f_{x-3} fx??cx=cx?1?fx?1??cx?2?fx?2??cx?3?fx?3?
设 g x = f x ? c 2 x g_x=f_{x} \cdot c^{2x} gx?=fx??c2x则这道题变为简单递推
发现 f n ≤ 1 0 9 f{_n}\le10^{9} fn?≤109这也就是说这个数质因子个数不超过30个,我们分别求出各个数的质因子,那么数的乘法就是质因子的相加
最后求个逆元回推就好了
这道题用到的两个思想都是非常常见的,下次做题要优先考虑
CF评论区里有个神人,直接把 c c c放进矩阵了…orz
Code

#include using namespace std; const int mod=1e9+7; struct mat { long long a[5][5]; mat operator *(const mat z) { mat f; memset(f.a,0,sizeof(f.a)); for(int i=1; i<=3; i++) for(int j=1; j<=3; j++) for(int k=1; k<=3; k++) f.a[i][j]=(f.a[i][j]+a[k][j]*z.a[i][k]%(mod-1))%(mod-1); return f; } friend ostream &operator <<(ostream &output,const mat &qq) { for(int i=1; i<=3; i++,output<mp; int num[4][55]; void work(int nm,long long x) { mat dd=e; while(x) { // cout>=1; } } long long ksm(long long x,long long a) { long long re=1; while(a) { if(a&1)re=re*x%mod; x=x*x%mod; a>>=1; } return re; } long long exgcd(long long a,long long b,long long &x,long long &y) { if(b==0) { x=1; y=0; return a; } int t=exgcd(b,a%b,y,x); y-=a/b*x; return t; } int main() { e.a[1][2]=e.a[2][3]=e.a[3][1]=e.a[3][2]=e.a[3][3]=1; scanf("%lld%lld%lld%lld%lld",&n,&f1,&f2,&f3,&c); f1=f1*c%mod; f2=f2*c%mod*c%mod; f3=f3*c%mod*c%mod*c%mod; long long k1=f1,k2=f2,k3=f3; for(int i=2; i<=sqrt(f1); i++) { if(k1%i==0) { p[++o]=i; while(k1%i==0) { k1/=i; } } if(k1==1)break; } if(k1!=1)p[++o]=k1; for(int i=2; i<=sqrt(f2); i++) { if(k2%i==0) { p[++o]=i; while(k2%i==0) { k2/=i; } } if(k2==1)break; } if(k2!=1)p[++o]=k2; for(int i=2; i<=sqrt(f3); i++) { if(k3%i==0) { p[++o]=i; while(k3%i==0) { k3/=i; } } if(k3==1)break; } if(k3!=1)p[++o]=k3; sort(p+1,p+1+o); o=unique(p+1,p+1+o)-p-1; for(int i=1; i<=o; i++) { mp[p[i]]=i; } k1=f1,k2=f2,k3=f3; for(int i=2; i<=sqrt(f1); i++) { if(k1%i==0) { while(k1%i==0) { k1/=i; num[1][mp[i]]++; } } if(k1==1)break; } if(k1!=1)num[1][mp[k1]]++; for(int i=2; i<=sqrt(f2); i++) { if(k2%i==0) { while(k2%i==0) { k2/=i; num[2][mp[i]]++; } } if(k2==1)break; } if(k2!=1)num[2][mp[k2]]++; for(int i=2; i<=sqrt(f3); i++) { if(k3%i==0) { while(k3%i==0) { // cout<【cf|Codeforces1182E Product Oriented Recurrence(递推+矩乘快速幂)】ans=ans*ksm(p[i],prime[i].a[3][1])%mod; // cout< } long long modp,y; c=ksm(c,n); exgcd(c,mod,modp,y); //cout<<"??"; modp=(modp%mod+mod)%mod; printf("%lld",ans*modp%mod); return 0; }

    推荐阅读