2019 ICPC Nanchang Network Competition H. The Nth Item

2019 ICPC Nanchang Network Competition H. The Nth Item


The main idea of ​​the topic : Know a sequence F(n):
F(0)=0, F(1)=1
F(n)=3∗F(n−1)+2∗F(n−2),(n ≥2
)

Give you a number of operations Q, and give you an initial value of n, let A1=F(n1), A2=F(n2),...Aq=F(nq), where n1=n, ni=Ai-1* Ai-1^ni-1, output the XOR sum of all A.

Solution : Steal the chicken successfully! I don’t know how many people pre-process according to the problem solution to reduce the complexity. It is estimated that most of them are not correct solutions. First of all, F(n) is a Fibonacci-like sequence, and the first reaction matrix is ​​a fast exponentiation. It takes O(1) to ask 10 7
at first glance ! plan to go bust. After reading the question carefully, I found that it is XOR, and it must be operated online, but how can I know the answer directly in a constant time? We tried to find the cycle section of F(n), but failed again. The modulus was too large and we couldn’t find it, but the formula of F(n) was pushed out. With the root number 17, fast exponentiation is not possible. The teammate finds the replacement number of the root number 17 under the modulus, converts it, and reduces the complexity of each query to log. It only needs a few fast exponentiations, and there is no matrix constant. Because there are a lot of people who have passed it, I thought that the data is very watery, and it is enough to reduce it to log, so I tried to submit a post. You thought it was AC? TLE!!! Sure enough, no matter how hard you work, it will be in vain. I was thinking of giving up, but my teammates had nothing to do and made a watch, and it was a loop! Immediately changed a few n and made a few more tables. I was surprised to find that after Q reached 10 5 , I don’t know why, the answer would loop. Divide Q into odd and even numbers, and then send AC.


Below is the AC code:

#include <bits/stdc++.h>
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;
}

Guess you like

Origin blog.csdn.net/yzsjwd/article/details/100636558
Recommended