BZOJ 3329 - Xorequ - 数位DP, 矩乘
Solution
发现 $x \ xor \ 2x = 3x$ 仅当 $x$ 的二进制中没有相邻的 $1$
对于第一个问题就可以进行数位DP 了。
但是对于第二个问题, 我们只能通过递推 打表 来算出答案了。
推公式 打表 可知, 这是一个斐波那契数列, $a_0 = 1, a_1 = 2, a_2 = 3$....
通过矩阵快速幂优化递推就可以过啦
Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define rd read() 5 #define ll long long 6 using namespace std; 7 8 const int mod = 1e9 + 7; 9 10 const int N = 70; 11 12 int T, a[100]; 13 ll sum[N][2], n; 14 15 struct matrix { 16 ll s[4][4]; 17 matrix operator * (const matrix &b) const { 18 matrix re; 19 memset(re.s, 0, sizeof(re.s)); 20 for(int i = 1; i <= 2; ++i) 21 for(int k = 1; k <= 2; ++k) 22 for(int j = 1; j <= 2; ++j) 23 re.s[i][j] = (re.s[i][j] + s[i][k] * b.s[k][j]) % mod; 24 return re; 25 } 26 }ans, st; 27 28 struct node { 29 int id; 30 ll in, out1, out2; 31 }b[1005]; 32 33 ll read() { 34 ll X = 0 , p = 1; char c = getchar(); 35 for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1; 36 for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0'; 37 return X * p; 38 } 39 40 ll dfs(int pos, int pre, int lim, int lead) { 41 if(!pos) return lead == 0; 42 if(!lim && !lead && sum[pos][pre] != -1) 43 return sum[pos][pre]; 44 int up = lim ? a[pos] : 1; 45 ll tmp = 0; 46 for(int i = 0; i <= up; ++i) { 47 if(pre && i) 48 continue; 49 tmp += dfs(pos - 1, i, lim && a[pos] == i, lead && i == 0); 50 } 51 if(!lim && !lead) 52 sum[pos][pre] = tmp; 53 return tmp; 54 } 55 56 ll work(ll x) { 57 int len = 0; 58 while(x) a[++len] = x % 2, x /= 2; 59 return dfs(len , 0, true, true); 60 } 61 62 inline bool cmp1(const node &A, const node &B ) { 63 return A.in < B.in; 64 } 65 66 inline bool cmp2(const node &A, const node &B) { 67 return A.id < B.id; 68 } 69 70 void print(ll x) { 71 sort(b + 1, b + 1 + T, cmp1); 72 memset(sum, -1, sizeof(sum)); 73 memset(st.s, 0, sizeof(st.s)); 74 memset(ans.s, 0, sizeof(ans.s)); 75 st.s[1][2] = st.s[2][1] = st.s[2][2] = 1; 76 ans.s[1][1] = 1; 77 ans.s[1][2] = 2; 78 printf("%lld\n", work(x)); 79 for(; x; x >>= 1, st = st * st) 80 if(x & 1) ans = ans * st; 81 printf("%lld\n", (ans.s[1][1] % mod + mod) % mod); 82 } 83 84 int main() 85 { 86 T = rd; 87 for(; T; T--) print(rd); 88 } 89