E. Product Oriented Recurrence(矩阵快速幂+欧拉降幂)

Posted letlifestop

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 

 

以上是关于E. Product Oriented Recurrence(矩阵快速幂+欧拉降幂)的主要内容,如果未能解决你的问题,请参考以下文章

Product Oriented Recurrence(Codeforces Round #566 (Div. 2)E+矩阵快速幂+欧拉降幂)

Codeforces Round #344 (Div. 2) E. Product Sum 二分斜率优化DP

Clojure - recur 适用于循环或 let 语句?

html jsPatterns.recur.trampoline.js

RECUR宣布与三丽鸥建立NFT战略合作关系,首次将标志性品牌Hello Kitty引入数字藏品空间

10 斐波那契数列