对于一个数列
求前n相的平方和
设
可得到
对于前n相和
可以发现重复项和
可得
根据得到的不变项可得
需要注意将负数加mod取模之后处理成正数
数据很大 连续取mod可能超时
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <string>
#include <cstring>
#include <string.h>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
using namespace std;
#define sp system("pause")
typedef long long ll;
typedef pair<int, int> pii;
ll mod;
struct Matrix
{
ll m[5][5];
int size;
void E()
{
for (int i = 0; i < 5; i++)for (int j = 0; j < 5; j++)m[i][j] = (i == j ? 1 : 0);
}
void clear()
{
for (int i = 0; i < 5; i++)for (int j = 0; j < 5; j++)m[i][j] = 0;
}
Matrix operator*(Matrix &x)
{
Matrix res;
res.size = x.size;
res.clear();
for (int i = 0; i < x.size; i++)
{
for (int j = 0; j < x.size; j++)
{
res.m[i][j] = 0;
for (int k = 0; k < x.size; k++)
{
res.m[i][j] += (m[i][k] * x.m[k][j]) % mod;
}
res.m[i][j] %= mod;
}
}
return res;
}
Matrix operator^(ll plus)
{
Matrix res;
res.E();
res.size = size;
Matrix a = *this;
while (plus)
{
if (plus & 1)res = res*a;
a = a*a;
plus >>= 1;
}
return res;
}
void to()
{
for (int i = 0; i < 5; i++)for (int j = 0; j < 5; j++)m[i][j] = (m[i][j] + mod) % mod;
}
};
int main()
{
int T;
cin >> T;
while (T--)
{
ll p, n;
scanf("%lld%lld%lld", &p, &n, &mod);
ll to2 = p;
Matrix b;
p <<= 1;
p %= mod;
b.size = 4;
b.clear();
b.m[0][0] = 1;
b.m[0][1] = p*p%mod;
b.m[0][2] = 1;
b.m[0][3] = ((-p + mod) % mod) * 2 % mod;
b.m[1][0] = 0;
b.m[1][1] = b.m[0][1];
b.m[1][2] = b.m[0][2];
b.m[1][3] = b.m[0][3];
b.m[2][0] = b.m[2][2] = b.m[2][3] = 0;
b.m[2][1] = 1;
b.m[3][0] = b.m[3][2]=0;
b.m[3][1] = p;
b.m[3][3] = (-1 + mod) % mod;
Matrix ans;
ans.size = 4;
ans.clear();
if (n <= 2)
{
ll aa = 0;
if (n == 1)
{
puts("1");
}
else if (n == 2)
{
printf("%lld\n", (1 + (to2)*(to2)) % mod);
}
}
else
{
n -= 2;
ans.m[0][0] = (1 + to2*to2) % mod;
ans.m[1][0] = (to2*to2) % mod;
ans.m[2][0] = 1;
ans.m[3][0] = (to2);
b = b^n;
ans = b*ans;
printf("%lld\n", ans.m[0][0]);
}
}
}