题意

给定五个整数 \(n,f_1,f_2,f_3,c\),其中数列 \(f\) 满足以下递推式:

\[f_x=c^{2x-6}f_{x-1}f_{x-2}f_{x-3}
\]

求 \(f_n\)。

\(\texttt{Data Range:}4\leq n\leq 10^{18},1\leq f_1,f_2,f_3,c\leq 10^9\)

题解

矩阵快速幂。

首先这个乘起来的东西显然没有什么方法去递推,然而从递推式中可以直接看出 \(f_n\) 是类似于 \(c^gf_1^{i}f_2^{j}f_3^{k}\) 的形式,所以考虑把每个次数算出来然后快速幂。

注意到这个次数很好算的。设 \(f_n\) 中 \(c\) 的次数为 \(g_n\),那么显然有递推式

\[g_n=2n-6+g_{n-1}+g_{n-2}+g_{n-3}=2(n-1)-4+g_{n-1}+g_{n-2}+g_{n-3}
\]

注意到这个东西是常见的非齐次线性递推模样,于是可以高高兴兴的走一波矩阵:

\[\begin{pmatrix}g_n\\g_{n-1}\\g_{n-2}\\n\\1\end{pmatrix}=\begin{pmatrix}1&1&1&2&-4\\1&0&0&0&0\\0&1&0&0&0\\0&0&0&1&1\\0&0&0&0&1\end{pmatrix}\begin{pmatrix}g_{n-1}\\g_{n-2}\\g_{n-3}\\n-1\\1\end{pmatrix}
\]

然后考虑递推 \(f_1,f_2,f_3\) 的次数。以 \(f_1\) 为例,设 \(f_n\) 中 \(f_1\) 的次数为 \(h_n\),那么有

\[h_n=h_{n-1}+h_{n-2}+h_{n-3}
\]

这个转移矩阵挺好写的,也就是:

\[\begin{pmatrix}h_n\\h_{n-1}\\h_{n-2}\end{pmatrix}=\begin{pmatrix}1&1&1\\1&0&0\\0&1&0\end{pmatrix}\begin{pmatrix}h_{n-1}\\h_{n-2}\\h_{n-3}\end{pmatrix}
\]

同时注意到 \(f_2\) 和 \(f_3\) 次数的递推式也是这个东西,只不过 \(h_1,h_2,h_3\) 不同而已,于是这个也可以递推出来了,然后就做完了。

代码

#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long long int li;
const ll MAXN=2e5+51,MOD=1e9+7;
struct Matrix{
ll num[6][6];
Matrix()
{
memset(num,0,sizeof(num));
}
inline ll* operator [](const ll &x)
{
return num[x];
}
inline const ll* operator [](const ll &x)const
{
return num[x];
}
};
Matrix mat,mat2,x,x2;
ll f1,f2,f3,c,res;
li n;
inline li read()
{
register li num=0,neg=1;
register char ch=getchar();
while(!isdigit(ch)&&ch!='-')
{
ch=getchar();
}
if(ch=='-')
{
neg=-1;
ch=getchar();
}
while(isdigit(ch))
{
num=(num<<3)+(num<<1)+(ch-'0');
ch=getchar();
}
return num*neg;
}
inline ll qpow(ll base,ll exponent)
{
ll res=1;
while(exponent)
{
if(exponent&1)
{
res=(li)res*base%MOD;
}
base=(li)base*base%MOD,exponent>>=1;
}
return res;
}
inline Matrix operator *(Matrix x,Matrix y)
{
Matrix res;
for(register int i=1;i<=5;i++)
{
for(register int j=1;j<=5;j++)
{
for(register int k=1;k<=5;k++)
{
res[i][j]=(res[i][j]+(li)x[i][k]*y[k][j]%(MOD-1))%(MOD-1);
}
}
}
return res;
}
inline Matrix qpow(Matrix base,li exponent)
{
Matrix res;
for(register int i=1;i<=5;i++)
{
res[i][i]=1;
}
while(exponent)
{
if(exponent&1)
{
res=res*base;
}
base=base*base,exponent>>=1;
}
return res;
}
int main()
{
n=read(),f1=read(),f2=read(),f3=read(),c=read(),res=1;
mat[1][1]=mat[2][1]=mat[3][1]=mat[1][2]=mat[2][3]=mat[4][4]=mat[5][4]=1;
mat[5][5]=x[1][5]=mat2[1][1]=1,mat[4][1]=2,mat[5][1]=MOD-5,x[1][4]=3;
mat2[2][1]=mat2[3][1]=mat2[1][2]=mat2[2][3]=x2[1][3]=1;
res=qpow(c,(x*qpow(mat,n-3))[1][1]);
res=(li)res*qpow(f1,(x2*qpow(mat2,n-3))[1][1])%MOD,x2[1][3]=0,x2[1][2]=1;
res=(li)res*qpow(f2,(x2*qpow(mat2,n-3))[1][1])%MOD,x2[1][2]=0,x2[1][1]=1;
res=(li)res*qpow(f3,(x2*qpow(mat2,n-3))[1][1])%MOD,printf("%d\n",res);
}

CodeForces 1182E Product Oriented Recurrence的更多相关文章

  1. codeforces 1182E Product Oriented Recurrence 矩阵快速幂

    题意:设f(n) = c ^ (2n - 6) * f(n - 1) * f(n - 2) * f(n - 3), 问第n项是多少? 思路:官方题解:我们先转化一下,令g(x) =  c ^ x * ...

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

    传送门 题目 \[ \begin{aligned} &f_n=c^{2*n-6}f_{n-1}f_{n-2}f_{n-3}&\\ \end{aligned} \] 思路 我们通过迭代发 ...

  3. CF1182E Product Oriented Recurrence

    思路: fn = can * f1xn * f2yn * f3zn, 首先dp计算指数部分an = an-1 + an-2 + an-3 + 2 * n - 6, 而an-1 = an-2 + an- ...

  4. cf 1182 E - Product Oriented Recurrence

    当时脑残了, 不会写矩阵快速幂中更改的系数, 其实把他扔到矩阵里同时递推就好了 #include<cstdio> #include<algorithm> #include< ...

  5. codeforces Unusual Product

    题意:给你n*n的矩阵,里面是1或0,然后q次询问,如果操作数为1,那么就把x行的数0变成1,1变成0:如果操作数为2,那么在x列上的数0变成1,1变成0:如果是3,输出: 思路:在求的时候,对角线上 ...

  6. Codeforces 631E Product Sum 斜率优化

    我们先把问题分成两部分, 一部分是把元素往前移, 另一部分是把元素往后移.对于一个 i 后的一个位置, 我们考虑前面哪个移到这里来最优. 我们设最优值为val,   val = max(a[ j ] ...

  7. @codeforces - 631E@ Product Sum

    目录 @desription@ @solution@ @accepted code@ @details@ @desription@ 给定一个序列 a,定义它的权值 \(c = \sum_{i=1}^{ ...

  8. Codeforces 1294C - Product of Three Numbers

    题目大意: 给定一个n,问是否存在3个互不相同的,大于等于2的整数,满足a*b*c=n 解题思路: 可以把abc其中任意两个看作一个整体,例如a*b=d,那么可以发现d*c=n 所以d和c是n的因子 ...

  9. Codeforces Round #566 (Div. 2)

    Codeforces Round #566 (Div. 2) A Filling Shapes 给定一个 \(3\times n\) 的网格,问使用 这样的占三个格子图形填充满整个网格的方案数 如果 ...

随机推荐

  1. C#方法Extra

    C#方法Extra 上次说的只是方法的一些基本东西,今天讲讲重载和 Lambda 表达式. 重载 方法的重载(overload)指的是同一个名字的方法,有着不一样的方法签名(method signat ...

  2. JQuery实现tab页

    用ul 和 div 配合实现tab 页 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="U ...

  3. Python-如何在一个for循环中迭代多个可迭代对象?

    案例: 某班学生期末考试成绩,语文.数学.英语分别存储在3个列表中,同时迭代三个列表.,计算每个学生的总分(并行) 某年级有4个班,某次英语成绩分别记录在4个列表中,依次迭代每个列表,统计全年级高于9 ...

  4. How to read h5 file by Matlab

    In matlab, one can use the following command to read h5 file data = h5read(filename,ds) data = h5rea ...

  5. logging模块培训小结

    Python自动化课程又上了一节课,每一个自动化框架都涉及到日志的使用,logging模块是Python的一个标准库模块,由标准库模块提供日志记录API的关键好处是所有Python模块都可以使用这个日 ...

  6. 腾讯云Elasticsearch集群规划及性能优化实践

    ​一.引言 随着腾讯云 Elasticsearch 云产品功能越来越丰富,ES 用户越来越多,云上的集群规模也越来越大.我们在日常运维工作中也经常会遇到一些由于前期集群规划不到位,导致后期业务增长集群 ...

  7. 日志分析平台ELK之搜索引擎Elasticsearch集群

    一.简介 什么是ELK?ELK是Elasticsearch.Logstash.Kibana这三个软件的首字母缩写:其中elasticsearch是用来做数据的存储和搜索的搜索引擎:logstash是数 ...

  8. Java知识系统回顾整理01基础04操作符05赋值操作符

    一.赋值操作 赋值操作的操作顺序是从右到左 int i = 5+5; 首先进行5+5的运算,得到结果10,然后把10这个值,赋给i public class HelloWorld { public s ...

  9. 在 Visual Studio 中创建一个简单的 C# 控制台应用程序

    转载:https://blog.csdn.net/qq_43994242/article/details/87260824 快速入门:使用 Visual Studio 创建第一个 C# 控制台应用 h ...

  10. 1个LED灯闪烁的Arduino控制

    控制任务和要求 让一个LED灯闪烁 接线 程序设计 1 int half_cycle=1000; // define the cycle time of LED blink 2 int LED_pin ...