幻想乡数学竞赛,Loj6692,特征方程

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/Deep_Kevin/article/details/102585871

正题

      Portal

      我这辈子都不会忘了特征根的。

      发现式子很难看,怎么带了一个3^n考虑把它消掉:

      3a_n=9a_{n-1}+3a_{n-2}-9a_{n-3}+3^{n+1}

      a_{n+1}=3a_n+a_{n-1}-3a_{n-2}+3^{n+1}

      那么下减上就可以消掉了,变成:a_{n+1}=6a_n-8a_{n-1}-6a_{n-2}+9a_{n-3}

      根据高阶递推式的特征方程我们可以知道:

      \\x^4=6x^3-8x^2-6x+9\\ x^4-6x^3+8x^2+6x-9=0 \\(x-1)(x+1)(x-3)(x-3)=0

      四个根就很显然了,发现有两个重根:a_n=A+(-1)^nB+(Cn+D) 3^n

      那么我们只要把A,B,C,D解出来就可以了。

      然后用光速幂和欧拉定理就可以做到小常数的O(T)了!

#include<bits/stdc++.h>
using namespace std;

const int block=1<<16;
long long A[block],B[block],d=281250002;
int T;
const long long mod=1e9+7;

void prepare(){
	A[0]=1;A[1]=3;for(int i=2;i<block;i++) A[i]=A[i-1]*A[1]%mod;
	B[0]=1;B[1]=A[block-1]*A[1]%mod;for(int i=2;i<block;i++) B[i]=B[i-1]*B[1]%mod;
}

namespace Mker
{
//  Powered By Kawashiro_Nitori
//  Made In Gensokyo, Nihon
	#include<climits>
	#define ull unsigned long long
	#define uint unsigned int
	ull sd;int op;
	inline void init() {scanf("%llu %d", &sd, &op);}
	inline ull ull_rand()
	{
		sd ^= sd << 43;
		sd ^= sd >> 29;
		sd ^= sd << 34;
		return sd;
	}
	inline ull rand()
	{
		if (op == 0) return ull_rand() % USHRT_MAX + 1;
		if (op == 1) return ull_rand() % UINT_MAX + 1; 
		if (op == 2) return ull_rand();
	}
}

long long Mi3(unsigned long long n){
	return A[n%block]*B[n/block]%mod;
}

int main(){
	scanf("%d",&T);
	Mker::init();
	prepare();
	long long last=0;
	while(T--){
		unsigned long long n=Mker::rand();
		long long ans=36,tmp=Mi3((n+2)%(mod-1))*(4*(n%mod)-13+mod)%mod;
		n&1?ans+=15:ans-=15;
		ans=(ans+tmp)*d%mod;
		last^=ans;
	}
	printf("%lld\n",last);
}

猜你喜欢

转载自blog.csdn.net/Deep_Kevin/article/details/102585871