2019ICPC(南昌) - The Nth Item(矩阵快速幂)

题目链接:点击查看

题目大意:给定一个变形版的斐波那契数列,F(n)为其对应的函数值,初始时给定一个q和一个a1,规定下面两个递推式:

  1. A_{n}=F(A_{n})
  2. A_{n+1}=A_{n}*A_{n}^A_{n}
  3. ans^=A_{n}

最后输出ans

题目分析:对于变形版的斐波那契函数,因为给出的n的范围到了1e18,所以肯定不能打表预处理,只能用矩阵快速幂,每次查询都是logn级别的时间复杂度,而总的需要迭代q次,即最坏情况到了1e7*log1e18,是4e8,如果直接交肯定会T掉,我们一开始是想找循环节,找An=An+1的时候,虽然没找到什么规律,但是却发现等到数很大的时候,ans就不会再改变了,也就是说每次斐波那契函数只需要记忆化一下,返回一个值即可,而不需要每次都重复计算,也就是用记忆化搜索的思想,该怎么实现呢?昨天刚学了一手unordered_map可以O1查找,所以就加了这句话优化了一下,就直接过了。。也不知道是碰上正解了还是数据水了,正解的话有些麻烦,是将原斐波那契数列化为一般式,然后转化成通过两次矩阵快速幂求得答案,并且预处理快速幂的答案(转换后的数据范围小多了),这样就能达到O1查询,也就是最坏情况也只有1e7了

上代码吧:

暴力+unordered_map:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include//C++11
using namespace std;
 
typedef long long LL;
 
const int N=2;
 
const LL M=998244353;
 
LL n,q;
 
struct Ma
{
	LL a[N][N];
};
 
Ma operator *(Ma a,Ma b)
{
	Ma temp;
	for(int i=0;i>=1;
	}
	return ans;
}

unordered_map mp; 

LL F(LL x)
{
	if(mp[x])
		return mp[x];
	if(x==0)
		return 0;
	if(x==1)
		return 1;
	Ma ans;
	ans.a[0][0]=3;
	ans.a[0][1]=1;
	ans.a[1][0]=2;
	ans.a[1][1]=0;
	ans=Pw(ans,x-1);
	Ma temp;
	temp.a[0][0]=1;
	temp.a[0][1]=0;
	return mp[x]=(temp*ans).a[0][0];
}
 
int main()
{
	while(scanf("%lld%lld",&q,&n)!=EOF)
	{
		int i;
		LL n1=n;
		LL a1=F(n1);
		LL ans=a1;
		for(i=2;i<=q;i++)
		{
			n1^=(a1*a1);	
			a1=F(n1);
			ans^=a1;
		}
		printf("%lld\n",ans);
	}
 
 
 
 
 
 
 
 
 
	return 0;
}

 

你可能感兴趣的:(矩阵快速幂)