meaning of the title
Given the parameters \ (C_1,C_2,P \), a sequence \ (x \) of length \ (n \times m \) is generated as follows:
\(x_0 = C_1,x_1=C2\)
\(x_i=(x_{i-1}+x_{i-1}) \% P \; (i > 1)\)
Then generate a sequence \ (a \) of length \ (n \times m \) as follows
\[a_i=\sum\limits_{j=0}^ix_j^2\%P\]
Now, I will perform \ (Q \) operations, and give two parameters \ (k1,k2 \) for each operation. Represents the value of exchange \ (k1,k2 \).
Then put the sequence \ (a \) into a \ (n \times m \) grid in order.
A scheme is required to make the number from \ ((1,1) \) to \ ((n,m) \) in the least lexicographic order.
thinking
It's easy to find, in fact, it's just to find out \ (a \).
Then push it.
\[x_i^2=x_{i-1}^2+2x_{i-1}x_{i-2}+x_{i-2}^2\]
\[x_{i-1}^2=x_i^2-x_{i-2}^2-2x_{i-1}x_{i-2}\]
\[x_{i-1}^2=(x_i+x_{i-2})\times(x_i-x_{i-2}) - 2x_{i-1}x_{i-2}\]
\[x_{i-1}^2=x_{i-1}(x_i+x_{i-2}) - 2x_{i-1}x_{i-2}\]
\[x_{i-1}^2=x_ix_{i-1}+x_{i-1}x_{i-2}-2x_{i-1}x_{i-2}\]
\[x_{i-1}^2=x_ix_{i-1}-x_{i-1}x_{i-2}\]
In other words
\[x_i^2=x_{i+1}x_i-x_ix_{i-1}\]
It's easy to get
\[a_i=x_{i+1}x_i-C_1(C_2-C_1)\]
So as long as we can quickly find the \ (i \) term of Fibonacci sequence.
If every matrix is directly raised to a fast power \ (TLE \)
So we preprocess the transfer matrix of \ (FBI ﹐ 1, FBI ﹐ 2, FBI ﹐ 3... FBI ﹐ m \) and \ (FBI ﹐ m, FBI {2m}, FBI {3M}... FBI {nm} \).
For the number of \ (i \) row and \ (j \) column, directly \ (O(2^3) \)
Code
#include<cstdio> #include<iostream> #include<cstdlib> #include<cmath> #include<ctime> #include<algorithm> #include<cstring> #include<bitset> #include<map> using namespace std; typedef long long ll; const int N = 500000 + 100,INF = 1e9 + 7; map<ll,ll>ma; ll read() { ll x=0,f=1;char c=getchar(); while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x*f; } int C1,C2,mod,n,m,Q; namespace FBI { struct node { int a[3][3],n,m; node() { memset(a,0,sizeof(a)); } node(int x) { n = m = x; memset(a,0,sizeof(a)); for(int i = 1;i <= x;++i) a[i][i] = 1; } node(int x,int y) { n = x,m = y; memset(a,0,sizeof(a)); } }; node operator * (const node &A,const node &B) { int n = A.n,m = B.m,K = A.m; node ret(n,m); for(int k = 1;k <= K;++k) { for(int i = 1;i <= n;++i) { for(int j = 1;j <= m;++j) { ret.a[i][j] += 1ll * A.a[i][k] * B.a[k][j] % mod; ret.a[i][j] %= mod; } } } return ret; } node fbi(1,2),tmp(2,2),lin[N],row[N]; void pre() { fbi.a[1][1] = C2,fbi.a[1][2] = C1; tmp.a[1][1] = tmp.a[1][2] = tmp.a[2][1] = 1; row[0].n = row[0].m = 2;row[0].a[1][1] = row[0].a[2][2] = 1; for(int i = 1;i <= m;++i) row[i] = row[i - 1] * tmp; lin[0].n = lin[0].m = 2; lin[0].a[1][1] = lin[0].a[2][2] = 1; for(int i = 1;i <= n;++i) lin[i] = lin[i - 1] * row[m]; } int solve(ll x) { if(x == -1) return (C2 - C1 + mod) % mod; if(x == 0) return C1; if(x == 1) return C2; --x; int y = x % m; x /= m; return (fbi * lin[x] * row[y]).a[1][1]; } int main(ll x) { return (1ll * solve(x + 1) * solve(x) % mod - 1ll * C1 * (C2 - C1) % mod + mod) % mod; } } ll p(ll x,ll y) { ll z = (x - 1) * m + y; if(ma[z]) return ma[z]; return z; } ll cnt = 1,ans; void solve(int x,int y) { ++cnt; if(x == n && y == m) return; int down = INF,right = INF; if(x != n) down = FBI::main(p(x + 1,y)); if(y != m) right = FBI::main(p(x,y + 1)); if(down <= right) { ans += cnt * down % mod; ans %= mod; solve(x + 1,y); } else { ans += cnt * right % mod; ans %= mod; solve(x,y + 1); } return; } int main() { n = read(),m = read(),Q = read(),mod = read(),C1 = read(),C2 = read(); for(int i = 1;i <= Q;++i) { ll x = read(),y = read(),tx = x,ty = y; if(ma[x]) tx = ma[x]; if(ma[y]) ty = ma[y]; ma[x] = ty;ma[y] = tx; } FBI::pre(); if(ma[1]) ans += FBI::main(ma[1]),ans %= mod; else ans += FBI::main(1),ans %= mod; solve(1,1); cout<<ans; return 0; }