分治 ZJOI2012day1 數列 題解

2021-07-26 21:50:36 字數 1614 閱讀 4489

乙個數列,其中a[0]=0,a[1]=1,a[2*i]=a[i],a[2*i+1]=a[i]+a[i+1],給出t個n,求a[n]。

然後我們需要推出通用的處理方法來利用p和q,不難想到x要分奇偶討論:

1.x為奇數

我們假設已經求好了下面的p和q,現在要把p和q對應到x-1和x上來,不難發現p不變,而q=p+q。

2.x為偶數

同理,不難發現q不變,而p=p+q。

所以對於乙個x,進行dfs((x+1)/2)(ps:(x+1)/2就不用判斷奇偶性了),得到下一層的p和q(遞迴到x=1為止),根據上述方法求得新p和q,最後根據定義,q就是a[x]。

時間複雜度:o(t*log2(n)*高精度)

最後,關於記憶化:通過上方討論就可以發現每隔1,2層就會出現重複,所以使用記憶化就可以把許多二叉做成一叉,效率近似log2(n)但有差距,不過實際表現非常不錯(特別是多組資料可能會減少許多組),也是一種可行的策略。

#include

#include

#include

using

namespace

std;

const

int maxl=25,tt=10000; //壓4位

int te;

char s[maxl*4+5];

struct bignum //高精度結構體

int& operator (int i)

void

operator = (int x) while (x);} //過載和int類的=

bignum(int x)

void

operator = (const

char *s) //過載和char類的=

}bignum(const

char *s)

void print()

};bignum n,p,q,c,bn_one=1;

bool eoln(char ch)

int reads(char *s) //讀入字元陣列

void readln()

bignum operator + (bignum a,bignum b) //過載+

while (c[c[0]+1]) c[0]++;while (c[0]>1&&!c[c[0]]) c[0]--;

return c;

}bignum operator / (bignum a,int x) //過載/

void dfs(bignum x) //dfs求a[x]

//特判0

if (x[0]==1&&x[1]==1) //邊界條件

dfs((x+bn_one)/2); //先求出之前的p和q

if (x[1]&1) q=p+q; else p=p+q; //根據奇偶性求新的p和q

}int main()

return

0;}

ZJOI2018 Day1 簡要題解

乙個結論是,lk t lk t 的每個節點在原樹上是乙個不超過 k 1 k 1 個點的連通塊。考慮用括號序列列舉所有不同的有根樹,利用樹雜湊來去重,這樣的樹大概 1000 1000 個,然後答案就是它的貢獻乘上它在原樹上的出現次數。在原樹上的出現次數可以直接狀壓dp,可以加乙個剪枝,就是葉子單獨提出...

Day1 兩數之和

題目 給定乙個整數陣列 nums 和乙個目標值 target,請你在該陣列中找出和為目標值的那 兩個 整數,並返回他們的陣列下標。你可以假設每種輸入只會對應乙個答案。但是,你不能重複利用這個陣列中同樣的元素。示例 給定 nums 2,7,11,15 target 9 因為 nums 0 nums 1...

ZJOI2018外省選手醬油記Day1

上午考試。又爆零了 下午講完題後放假 然後就滾回去收拾行李準備去zj z j衢州?我怎麼從來沒聽過這個地方。肯定是我見識少 上高鐵出發,3個 小時3 個小 時,看了一下電影,頹了一會兒紅警,聊了聊qq q q,然後就到了 一下車發現一堆hn h n選手來參賽,怎麼也有 50 50 個以上吧 直接跑去...