题目解释
现有一数列:\(a_{0}=-3,a_{1}=-6,a_{2}=-12,a_{n}=3a_{n-1}+a_{n-2}-3a_{n-3}+3^n,求T组a_{n}\)mod p 的异或和
题目思路分析
抛开复杂度不谈,这道题可以用矩阵加速(矩阵的快速幂)和通项公式两种方法来做,这两种方法求一个\(a_{n}\)的时间复杂度都是\(log_2(n)\),但矩阵乘法需要更多时间,因此常数略大
总时间复杂度:
矩阵加速:O(\(16Tlog_2n\))
通项公式:O(\(Tlog_2n\))
而本题的T最大范围为[1,5e7],而n的最大可到\(2^{63}-1\),很显然,总时间复杂度的需求为O(n),尽管上述两种做法用快速幂实现都会TLE,但通项公式中的幂的底数固定,可以用光速幂预处理
因此整体思路为:先推通项公式,再用光速幂优化查询
通项公式推导
\(a_{n}=3a_{n-1}+a_{n-2}-3a_{n-3}+3^n\)
\(a_{n}-a_{n-2}=3(a_{n-1}-a_{n-3})+3^n\)
\(设a_{n}-a_{n-2}=b_{n} 得b_{2}=-9\)
\(b_{n}=3b_{n-1}+3^n\)
\(\frac{b_{n}}{3^n}=\frac{b_{n-1}}{3^n-1}+1\)
\(设\frac{b_{n}}{3^n}=c_{n} 得c_{2}=-1\)
\(c_{n}=c_{n-1}+1\)
\(c_{n}=c_{0}+n=c_{2}+n-2=-1+n-2=n-3\)
\(b_{n}=(n-3)3^n\)
\(a_{n}-a_{n-2}=(n-3)3^n\)
\(当n为偶数时 a_{n}=a_{0}+\sum_{i=1}^{\frac{n}{2}} (2i-3)3^{2i} =-3+\sum_{i=1}^{\frac{n}{2}} (2i-3)3^{2i}\)
\(设\sum_{i=1}^{\frac{n}{2}} (2i-3)3^{2i}=X\)
\(9X=9sum_{i=1}^{\frac{n}{2}} (2i-3)3^{2i}=sum_{i=1}^{\frac{n}{2}} (2i-3)3^{2i+2}\)
\(8X=9X-X=sum_{i=1}^{\frac{n}{2}} (2i-3)3^{2i+2}-sum_{i=1}^{\frac{n}{2}} (2i-3)3^{2i}\)
\(8X=(n-3)3^{(n+2)}+sum_{i=1}^{\frac{n}{2}-1} (2i-3)3^{2i+2}-sum_{i=2}^{\frac{n}{2}} (2i-3)3^{2i}+9\)
\(8X=(n-3)3^{(n+2)}-sum_{i=2}^{\frac{n}{2}} (2i-3-[2(i-1)-3])3^{2i}+9\)
\(8X=(n-3)3^{(n+2)}-sum_{i=2}^{\frac{n}{2}} 2*3^{2i}+9\)
\(8X=(n-3)3^{(n+2)}-\frac{3^(n+2)-3^4}{8}+9\)
\(X=\frac{(4n-13)3^{(n+2)}+117}{32}\)
\(a_{n}=\frac{(4n-13)3^{(n+2)}+117}{32}-3=\frac{(36n-117)3^n+21}{32}\)
\(当n为奇数时 a_{n}=a_{1}+\sum_{i=1}^{\frac{n}{2}} (2i-3)3^{2i}\)
同理\(a_{n}=\frac{(4n-13)3^{(n+2)}+51}{32}=\frac{(36n-117)3^{n}+51}{32}\)
代码实现
由于通项中所有幂的底数均为3,因此可以用光速幂预处理
其实现原理为\(a^{n}=a^{kx+y}=a^{kx}a^y\),分别预处理\(a^{kx}\)和\(a^y\)
具体实施如下
#define Q 32000
//预处理
gsm1[0]=gsm2[0]=1;
for(int i=1;i<=Q;i++)gsm1[i]=1ll*gsm1[i-1]*3%mod;
for(int i=1;i<=Q;i++)gsm2[i]=1ll*gsm2[i-1]*gsm1[Q]%mod;
//调用
int gsm(int n){
return 1ll*gsm2[n/Q]*gsm1[n%Q]%mod;
}
由于答案需要取模,除以一个数需改为乘以它的逆元,所以我们可以通过快速幂计算得32在1e9+7下的逆元为281250002(即\(32^{1e9+5} mod 1e9+7\))
而由于有时n过大,我们可以利用\(a^n≡a^{(n-1)mod{p}}(mod{p}))\)来化简
最后,计算时记得乘上1ll,每算一次都要取一次模防止超出long long的范围
AC代码
#include<bits/stdc++.h>
#define mod 1000000007
#define _32 281250002
#define Q 32000
using namespace std;
int gsm1[Q+1],gsm2[Q+1],rst,T;
int gsm(int n){
return 1ll*gsm2[n/Q]*gsm1[n%Q]%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();
}
}
int comput(unsigned long long x){
if(x&1)return 1ll*(1ll*(36*(x%mod)-117+mod)%mod*gsm(x%(mod-1))+51)%mod*_32%mod;
return 1ll*(1ll*(36*(x%mod)-117+mod)%mod*gsm(x%(mod-1))+21)%mod*_32%mod;
}
int main(){
scanf("%d",&T);
Mker::init();
gsm1[0]=gsm2[0]=1;
for(int i=1;i<=Q;i++)gsm1[i]=1ll*gsm1[i-1]*3%mod;
for(int i=1;i<=Q;i++)gsm2[i]=1ll*gsm2[i-1]*gsm1[Q]%mod;
while(T--){
rst^=comput(Mker::rand());
}
printf("%d",rst);
}