给你一个操作次数Q,再给你一个初始n的值,令A1=F(n1),A2=F(n2),…Aq=F(nq),其中n1=n,ni=Ai-1*Ai-1^ni-1,输出所有A的异或和。
解法:偷鸡成功!不知道多少人是按题解那样预处理来降低复杂度的,估计大多数都不是正解做法吧。
首先F(n)是类斐波那契数列,第一反应矩阵快速幂,一看询问107,要O(1)!计划破产。仔细读题发现是异或,一定要在线操作,但是怎么在常数时间内直接知道答案呢?我们尝试去找F(n)的循环节,再次失败,模数太大找不到,倒是把F(n)的公式推了出来。带根号17,无法快速幂,队友找到该模数下根号17的代替数,转换,把每次查询复杂度降到了log,只要几次快速幂就可以,没了矩阵的常数。因为过的人很多,就以为数据很水,降到log就可以了,于是尝试交了一发。
你以为AC了?TLE!!!果然再多努力都是白费。
本来想着放弃,队友没事干打了个表,循环了!马上换了几个n多打了几个表,惊奇的发现,在Q达到105以后,不知道为什么,答案会出现循环,把Q分
一下奇数偶数就可以,一发AC。
下面是AC代码:
#include
using namespace std;
using namespace chrono;
const int N = 100000005;
const int M = 998244353;
const int S = 473844410;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
const double eps = 1e-8;
#define ms(x, y) memset((x), (y), sizeof(x))
#define mc(x, y) memcpy((x), (y), sizeof(y))
typedef long long ll;
typedef unsigned long long ull;
#define fi first
#define se second
#define mp make_pair
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
#define bg begin
#define ed end
#define pb push_back
#define al(x) (x).bg(), (x).ed()
#define st(x) sort(al(x))
#define un(x) (x).erase(unique(al(x)), (x).ed())
#define fd(x, y) (lower_bound(al(x), (y)) - (x).bg() + 1)
#define ls(x) ((x) << 1)
#define rs(x) (ls(x) | 1)
template <class T>
bool read(T & x) {
char c;
while (!isdigit(c = getchar()) && c != '-' && c != EOF);
if (c == EOF) return false;
T flag = 1;
if (c == '-') { flag = -1; x = 0; } else x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
x *= flag;
return true;
}
template <class T, class ...R>
bool read(T & a, R & ...b) {
if (!read(a)) return false;
return read(b...);
}
mt19937 gen(steady_clock::now().time_since_epoch().count());
#define LL ll
LL a_b_MOD_c(LL a,LL b,LL mod){
assert(b >= 0);
LL ret = 1;
a %= mod;
while(b){
if(b & 1) ret = ret * a % mod;
a = a * a % mod;
b >>= 1;
}
return ret;
}
const int inv2 = a_b_MOD_c(2, M - 2, M);
const int invS = a_b_MOD_c(S, M - 2, M);
const int a = S + 3;
const int b = 3 - S + M;
//(x^2)%n=a 求平方剩余,n必须是奇素数
//注意:如果a为负,则看题意,是否要化为a=(a%n+n)%n
int modsqr(int a,int n){
int b,k,i,x;
if(n==2) return a%n;
if(a_b_MOD_c(a,(n-1)/2,n)==1){
if(n%4==3)
x=a_b_MOD_c(a,(n+1)/4,n);
else{
for(b=1;a_b_MOD_c(b,(n-1)/2,n)==1;b++){
i=(n-1)/2;
k=0;
}
do{
i/=2;
k/=2;
if((a_b_MOD_c(a,i,n)*a_b_MOD_c(b,k,n)+1)%n==0)
k+=(n-1)/2;
}
while(i%2==0);
x=(a_b_MOD_c(a,(i+1)/2,n)*a_b_MOD_c(b,k/2,n))%n;
}
if(x*2>n)
x=n-x;
return x;
}
return -1;
}
const int step = 100000;
int main()
{
time_point<steady_clock> start = steady_clock::now();
int Q;
ll n, ans = 0, plast, t = 0;
read(Q, n);
for (int i = 1; i <= Q; i++) {
ll last = n <= 1 ? n : (a_b_MOD_c(a, n, M) - a_b_MOD_c(b, n, M) + M) * invS % M * a_b_MOD_c(inv2, n, M) % M;
ans ^= last;
n ^= last * last;
if (i > 1) {
if (last == plast) {
t = i;
plast = last;
break;
}
}
plast = last;
}
// cout << "check 1: " << t << ' ' << plast << endl;
if (t && (Q - t) % 2 == 1)
ans ^= plast;
// cout << "check 2: " << t << ' ' << plast << endl;
printf("%lld\n", ans);
cerr << endl << "------------------------------" << endl << "Time: "
<< duration<double, milli>(steady_clock::now() - start).count()
<< " ms." << endl;
return 0;
}