传送门:https://nanti.jisuanke.com/t/31453
本题是一个组合数学(DP,滑稽)题。
一个环上有N个位置,标号为1~N。设第i(1≤i≤N)个位置上的数为x[i],限制条件为:0≤x[i]<2k。另有限制条件:当位置i和位置j相邻时,x[i]⊕x[j]≠2k-1。求满足限制条件的环的状态数。
可以考虑将环切割成链,以分析问题。设:
①a[n]:长度为n,且首尾相同的满足上述条件的链的状态数;
②b[n]:长度为n,且首尾相反的满足上述条件的链的状态数;
③c[n]:长度为n,其他的满足上述条件的链的状态数。
于是,有以下转移方程:
$\begin{cases}
\ a_n=a_{n-1}+c_{n-1} \\
\ b_n=b_{n-1}+c_{n-1} \\
\ c_n=(2^k-3)c_{n-1}
\end{cases}$
可以写成矩阵乘法的形式:
$\begin{pmatrix}
a_i\\
b_i\\
c_i
\end{pmatrix}
=\begin{pmatrix}
1 & 0 & 1\\
0 & 1 & 1\\
2^k-2 & 2^k-2 & 2^k-3
\end{pmatrix}
\begin{pmatrix}
a_{i-1}\\
b_{i-1}\\
c_{i-1}
\end{pmatrix}$
初始条件:
$\begin{pmatrix}
a_1\\
b_1\\
c_1
\end{pmatrix}
=\begin{pmatrix}
2^k\\
0\\
0
\end{pmatrix}$
可以通过矩阵快速幂在O(logN)时间内求解。
答案为$ans(N,k)=(2^k-1)a_{N-1}+(2^k-2)(b_{N-1}+c_{N-1})$。
参考程序如下(实现上引用了本人编写的矩阵类的部分代码):
#include <bits/stdc++.h> using namespace std; const int64_t mod = 1e9 + 7; int64_t pwr(int64_t x, int p) { if (p == 0) return 1; if (p & 1) return x * pwr(x, p ^ 1) % mod; return pwr(x * x % mod, p >> 1); } int64_t a[3][3]; #define MAX_N 3 /*** * Matrix is a type of 2D-array. * Here implements Basic Operators of Matrix. */ struct Matrix_t { int row, col; int64_t elem[MAX_N][MAX_N]; Matrix_t() {} Matrix_t(int row, int col) : row(row), col(col) {} Matrix_t(int row, int col, int64_t elem[][MAX_N]) { this->row = row; this->col = col; if (elem != nullptr) { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { this->elem[i][j] = elem[i][j]; } } } } Matrix_t(const Matrix_t& obj) { this->row = obj.row; this->col = obj.col; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { this->elem[i][j] = obj.elem[i][j]; } } } virtual ~Matrix_t() { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { elem[i][j] = 0; } } row = 0; col = 0; } Matrix_t& operator =(const Matrix_t& rhs) { row = rhs.row; col = rhs.col; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { elem[i][j] = rhs.elem[i][j]; } } return *this; } //Override: Matrix Multiplication. Matrix_t operator *(const Matrix_t& rhs) { int64_t res[MAX_N][MAX_N]; for (int i = 0; i < row; i++) { for (int j = 0; j < rhs.col; j++) { res[i][j] = 0; for (int k = 0; k < col; k++) { res[i][j] += elem[i][k] * rhs.elem[k][j] % mod; res[i][j] %= mod; } } } return Matrix_t(row, rhs.col, res); } }; /*** * Square Mairtx is a type of Matrix. * Here implements Integer Power of Square Matrix. */ struct SquareMatrix_t : Matrix_t { int sz; SquareMatrix_t() {} SquareMatrix_t(int sz) : Matrix_t(sz, sz), sz(sz) {} SquareMatrix_t(int sz, int64_t elem[][MAX_N]) : Matrix_t(sz, sz, elem), sz(sz) {} virtual ~SquareMatrix_t() { for (int i = 0; i < sz; i++) { for (int j = 0; j < sz; j++) { elem[i][j] = 0; } } sz = 0; } void init() { for (int i = 0; i < sz; i++) { elem[i][i] = 1; } } SquareMatrix_t& operator =(const Matrix_t& rhs) { sz = rhs.row; for (int i = 0; i < sz; i++) { for (int j = 0; j < sz; j++) { elem[i][j] = rhs.elem[i][j]; } } return *this; } SquareMatrix_t operator ^(int p) { SquareMatrix_t res(sz); SquareMatrix_t tmp(*this); res.init(); while (p) { if (p & 1) res = res * tmp; tmp = tmp * tmp; p >>= 1; } return res; } }; int main(void) { ios::sync_with_stdio(false); int t; cin >> t; while (t--) { memset(a, 0, sizeof(a)); int n, k; cin >> n >> k; int64_t p = pwr(2, k); if (n == 1) { cout << p << endl; continue; } a[0][0] = 1; a[0][2] = 1; a[1][1] = 1; a[1][2] = 1; a[2][0] = (p - 2 + mod) % mod; a[2][1] = (p - 2 + mod) % mod; a[2][2] = (p - 3 + mod) % mod; SquareMatrix_t mat(3, a); SquareMatrix_t res = mat ^ (n - 2); int64_t a = res.elem[0][0] * p % mod; int64_t b = res.elem[1][0] * p % mod; int64_t c = res.elem[2][0] * p % mod; int64_t ans = (a * ((p - 1 + mod) % mod) % mod + (b + c) % mod * ((p - 2 + mod) % mod) % mod) % mod; cout << ans << endl; } }
原文地址:https://www.cnblogs.com/siuginhung/p/9616106.html