首页 > 其他分享 >P5175 数列

P5175 数列

时间:2023-08-29 23:45:45浏览次数:38  
标签:数列 P5175 times a1 init bmatrix ans mod

Updated

2023.07.05 修正了一处笔误,在此感谢@DWT8125

题解

首先先推一下柿子,因为数据范围很大,所以考虑矩阵加速递推。

根据题意给的递推式,可得:

\[\begin{aligned} a_i^2 &= (x \times a_{i-1}+y \times a_{i-2})^2\\ &= x^2\times a_{i-1}^2+y^2\times a_{i-2}^2+2xy\times a_{i-1} \times a_{i-2} \end{aligned}\]

由此我们可以构造出答案矩阵:

\[T=\begin{bmatrix} a_i^2 & a_{i-1}^2 & a_i \times a_{i-1} &ans_i\\ \end{bmatrix}\]

其中 \(ans_i=\sum_{j=1}^i a_j^2\).

那么由于

\[\begin{cases} x^2\times a_{i-1}^2+y^2\times a_{i-2}^2+2xy\times a_{i-1} \times a_{i-2}+0 \times ans_{i-1}=a_i^2\\ 1\times a_{i-1}^2+0\times a_{i-2}^2+0\times a_{i-1} \times a_{i-2}+0 \times ans_{i-1}=a_{i-1}^2\\ x\times a_{i-1}^2+0\times a_{i-2}^2+y\times a_{i-1} \times a_{i-2}+0 \times ans_{i-1}=a_{i} \times a_{i-1}\\ x^2\times a_{i-1}^2+y^2\times a_{i-2}^2+2xy\times a_{i-1} \times a_{i-2}+1 \times ans_{i-1}=ans_i\\ \end{cases}\]

可得

\[\begin{bmatrix} a_{i-1}^2 & a_{i-2}^2 & a_{i-1} \times a_{i-2} &ans_{i-1}\\ \end{bmatrix} \times \begin{bmatrix} x^2 & 1 & x & x^2\\ y^2 & 0 & 0 & y^2\\ 2xy & 0 & y & 2xy\\ 0 & 0 & 0 & 1\\ \end{bmatrix}=T\]

因为我们已知第一第二项,所以只需得到转移矩阵的 \(n-2\) 次方即可,此时要特判 \(n=1\) 和 \(n=2\) 的情况,防止程序出错。

然后再套一下矩阵加速的板子就可以。

单次时间复杂度为 \(O(\log n \times m^3)\),其中 \(m\) 为矩阵边长,总时间复杂度为 \(O(T\log n \times m^3)\).

#include <cstdio>
#include <iostream>
#include <cstring>

using namespace std;

#define ll long long

const ll mod=1e9+7;

ll t,n,a1,a2,x,y;

struct matrix {
	int n,m;
	ll e[5][5];
	void clean() {
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=m;j++) {
				e[i][j]=0;
			}
		}
	}
};

matrix mul(matrix a,matrix b) {
	matrix ans;
	ans.n=a.n;
	ans.m=b.m;
	ans.clean();
	for(int i=1;i<=a.n;i++) {
		for(int j=1;j<=b.m;j++) {
			for(int k=1;k<=a.m;k++) {
				ans.e[i][j]=(ans.e[i][j]+(a.e[i][k]*b.e[k][j])%mod)%mod;
			}
		}
	}
	return ans;
}

matrix quickly_pow(matrix a,ll k) {
	matrix ans;
	ans.n=a.n;
	ans.m=a.m;
	for(int i=1;i<=ans.n;i++) {
		for(int j=1;j<=ans.m;j++) {
			if(i==j) ans.e[i][j]=1;
			else ans.e[i][j]=0;
		}
	}
	while(k) {
		if(k&1) ans=mul(ans,a);
		a=mul(a,a);
		k>>=1;
	}
	return ans;
}

int main() {
	scanf("%lld",&t);
	while(t--) {
		scanf("%lld%lld%lld%lld%lld",&n,&a1,&a2,&x,&y);
		if(n==1) {//特判
			printf("%lld\n",a1*a1%mod);
			continue;
		} else if(n==2) {
			printf("%lld\n",(a1*a1%mod+a2*a2%mod)%mod);
			continue;
		}
		matrix init;
		init.n=4;init.m=4;
		init.clean();
		init.e[1][1]=x*x%mod;init.e[1][2]=1;init.e[1][3]=x;init.e[1][4]=x*x%mod;
		init.e[2][1]=y*y%mod;init.e[2][4]=y*y%mod;
		init.e[3][1]=2*x%mod*y%mod;init.e[3][3]=y;init.e[3][4]=2*x%mod*y%mod;
		init.e[4][4]=1;
		init=quickly_pow(init,n-2);
		matrix ans;
		ans.n=1;ans.m=4;
		ans.clean();
		ans.e[1][1]=a2*a2%mod;ans.e[1][2]=a1*a1%mod;ans.e[1][3]=a1*a2%mod;ans.e[1][4]=(a1*a1%mod+a2*a2%mod)%mod;
		ans=mul(ans,init);
		printf("%lld\n",ans.e[1][4]);
	}
	return 0;
}

标签:数列,P5175,times,a1,init,bmatrix,ans,mod
From: https://www.cnblogs.com/Scorilon/p/17666145.html

相关文章

  • §3. 数列极限存在的条件
    掌握单调有界原理、致密性定理、柯西收敛准则,能够运用这些定理证明一个数列是否收敛。 设S为有界数集,则若,则存在严格递减数列,使得数列发散的充要条件是:存在,对任意的正整数N,总存在,使得重点习题:1、3(单调有界原理)、5-8.......
  • 剑指 Offer 10- I. 斐波那契数列(简单)
    题目:classSolution{//动态规划public:intfib(intn){if(n<=1)returnn;vector<int>dp(2,0);//确定dp数组以及下标的含义dp[0]=0;//dp数组初始化dp[1]=1;for(inti=2;i<=n;i++){//递推顺序从......
  • §1. 数列极限概念
    1. 掌握数列极限的定义,并会用语言证明给定数列的极限。如何用语言证明 :任给,研究,通过放缩得到一个比较简单的形式,然后分析得到n满足什么条件,能够使得.最后用语言总结:对任给的,只要取,则当时,.注意:N不一定限于正整数,只要是正数即可。2.掌握数列极限的几何意义和由此产生的新的定义......
  • §2. 收敛数列的性质
    1.掌握收敛数列的唯一性,有界性,保号性,保不等式性,迫敛性,四则运算。2.熟悉子列的定义以及子列极限和原数列极限的关系。当一个数列有一个子列发散,或有两个子列收敛但极限不相等,则数列一定发散。 重点习题:第1、2、4、6题,通过这些习题熟悉收敛数列性质的应用。 ......
  • 【剑指Offer】7、斐波那契数列
    【剑指Offer】7、斐波那契数列题目描述:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。假设n<=39。解题思路:斐波那契数列:0,1,1,2,3,5,8........总结起来就是:第一项是0,第二项是1,后续第n项为第n-1项和第n-2项之和。用公式描述如下:......
  • 动态规划--斐波那契数列
    博客地址:https://www.cnblogs.com/zylyehuo/#-*-coding:utf-8-*-#子问题的重复计算--递归方法--执行效率低deffibnacci(n):ifn==1orn==2:return1else:returnfibnacci(n-1)+fibnacci(n-2)#print(fibnacci(100))......
  • 四种解决”Arg list too long”参数列表过长的办法
    在linux中删除大量文件时,直接用rm会出现:-bash:/bin/rm:参数列表过长,的错误。这时可以用find命令来结合使用。例:1、rm*-rf改为:find.-name"*"|xargsrm-rf'*'就行了。2、rmtest*-rf改为:find.-name"test*"|xargsrm-rf"test*"mv时报参数列表过长,foriin*.m......
  • 代码随想录算法训练营第十三天|单调数列:滑动窗口最大值(力扣239.)、优先级队列:前k个高
    单调数列:滑动窗口最大值(力扣239.)给定滑动窗口的范围,求每个滑动窗口范围内的最大值使用单调队列实现对于最大值数字前面的数字不存入数列,对于最大值数字后面的数字存入数列中单调队列中数字的大小呈递减顺序pop(value):如果窗口移除的元素等于单调队列的队口元素,则pop;否则什......
  • (简单)计算斐波那契数列与阶乘
    斐波那契数列pythondeffibonacci(n):ifn<=0:return"Invalidinput"elifn==1:return0elifn==2:return1else:prev_1=0prev_2=1for_inrange(n-2):curre......
  • 回文数列
    #include<iostream>usingnamespacestd;boola(stringn){ if(n[0]==n[n.size()-1]){ if(n.size()<=3){ return1; }else{ n=n.substr(1,n.size()-2); a(n); return1; } }}intmain(intargc,char**argv){ stringn; cin>>n;......