Xorequ(BZOJ3329+数位DP+斐波那契数列)
生活随笔
收集整理的這篇文章主要介紹了
Xorequ(BZOJ3329+数位DP+斐波那契数列)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接
傳送門
思路
由\(a\bigoplus b=c\rightarrow a=c\bigoplus b\)得原式可化為\(x\bigoplus 2x=3x\)。
又異或是不進位加法,且\(2x=1<<x,3x=(1<<x)+x\),因此可知\((x\&2x)=0\),也就是說\(x\)的二進制中沒有相鄰的\(1\)。
第一問就可以用數位\(DP\)來寫。
對于第二問我們可以考慮遞推式,我們定義\(f(x)\)表示\(2^x\)時滿足等式的數的個數,則
- 如果第\(n\)位是\(1\),那么第\(n-1\)位就必須是\(0\),此時就相當于忽略第\(n,n-1\)位,轉變成最高位是\(n-2\)的個數,因此\(f(n)\)可以從第\(n-2\)位轉移過來;
- 如果第\(n\)位是\(0\),那么就相當于忽略第\(n\)位,轉變成最高位是\(n-1\)的個數,因此\(f(n)\)可以從第\(n-1\)位轉移過來。
最后得到遞推式\(f(n)=f(n-1)+f(n-2)\),也就是斐波那契數列,注意該遞推式中的\(n\)是指\(2\)進制中最高位是多少,也就是題目中的\(n-1\),因次本題答案是\(f(n+1)\)。
其實這兩個規律可以通過打表找出來的~
代碼
#include <set> #include <map> #include <deque> #include <queue> #include <stack> #include <cmath> #include <ctime> #include <bitset> #include <cstdio> #include <string> #include <vector> #include <cassert> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std;typedef long long LL; typedef pair<LL, LL> pLL; typedef pair<LL, int> pLi; typedef pair<int, LL> pil;; typedef pair<int, int> pii; typedef unsigned long long uLL;#define lson rt<<1 #define rson rt<<1|1 #define lowbit(x) x&(-x) #define name2str(name) (#name) #define bug printf("*********\n") #define debug(x) cout<<#x"=["<<x<<"]" <<endl #define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin) #define IO ios::sync_with_stdio(false),cin.tie(0)const double eps = 1e-8; const int mod = 1000000007; const int maxn = 50000 + 7; const double pi = acos(-1); const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3fLL;int t; LL n; int a[62]; int f[3], base[3][3]; LL dp[62][2][2][2];LL dfs(int pos, int pre, int flag, bool limits, bool lead) {if(pos == -1) return flag && (!lead);if(!limits && dp[pos][pre][flag][lead] != -1) return dp[pos][pre][flag][lead];int up = limits ? a[pos] : 1;LL ans = 0;for(int i = 0; i <= up; ++i) {if(i == 0) ans += dfs(pos - 1, 0, flag, limits && i == a[pos], lead);else ans += dfs(pos - 1, 1, flag && (pre != 1), limits && a[pos] == i, 0);}if(!limits) dp[pos][pre][flag][lead] = ans;return ans; }LL solve(LL x) {int len = 0;while(x) {a[len++] = x % 2;x >>= 1;}return dfs(len - 1, 0, 1, 1, 1); }void mul() {int c[3];memset(c, 0, sizeof(c));for(int i = 0; i < 2; ++i) {for(int j = 0; j < 2; ++j) {c[i] = (c[i] + 1LL * f[j] * base[j][i] % mod) % mod;}}memcpy(f, c, sizeof(c)); }void mulself() {int c[3][3];memset(c, 0, sizeof(c));for(int i = 0; i < 2; ++i) {for(int j = 0; j < 2; ++j) {for(int k = 0; k < 2; ++k) {c[i][j] = (c[i][j] + 1LL * base[i][k] * base[k][j] % mod) % mod;}}}memcpy(base, c, sizeof(c)); }int main() { #ifndef ONLINE_JUDGEFIN; #endifmemset(dp, -1, sizeof(dp));scanf("%d", &t);while(t--) {scanf("%lld", &n);printf("%lld\n", solve(n));base[0][0] = 1, base[0][1] = 1;base[1][0] = 1, base[1][1] = 0;f[0] = f[1] = 1;while(n) {if(n & 1) mul();mulself();n >>= 1;}printf("%d\n", f[0]);}return 0; }轉載于:https://www.cnblogs.com/Dillonh/p/11327901.html
總結
以上是生活随笔為你收集整理的Xorequ(BZOJ3329+数位DP+斐波那契数列)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Set 的合集 并集 差集
- 下一篇: 春运学生与民工