AtCoder Grand Contest 012 C:Tautonym Puzzle
阿新 • • 發佈:2018-11-30
ref def 現在 隊列 一個 lin gin mat 傳送門 。假設\(c\)並沒有出現在\(s\)裏,我們用兩種方式將\(c\)添加進\(s\)裏去:
題目傳送門:https://agc012.contest.atcoder.jp/tasks/agc012_c
題目翻譯
如果一個字符串是好的,那麽這個字符串的前半部分和後半部分肯定一模一樣。比如\(aa\)與\(bubobubo\)就是好的串,而空串,\(a\)與\(abcabcabc\)以及\(abba\)就不是好的。現在給你一個小於等於\(10^{12}\)的數字\(N\),要你求出一個字符串\(s\),使得這個串的\(2^{len}-1\)個子串裏剛好有\(N\)個子串是好的。要求\(len\leqslant 200\)。
題解
我們先欽點空串是好的,\(s=X+Y\),\(X\)與\(Y\)分別是子串裏只有空串是好串的字符串
第一種:\(s'=cX+Yc\),這樣的話\(s'\)的子串裏好串的數量會比\(s\)裏多\(1\)。
第二種:\(s'=Xc+Yc\),這樣的話\(s'\)的子串裏好串的數量會比\(s\)的多一倍。
只需要加一和乘二兩種操作就可以湊出所有的數,我們把\(N\)二進制分解一下用雙端隊列搞搞就可以了。
時間復雜度:\(O(logN)\)
空間復雜度:\(O(len)\)
代碼如下:
#include <deque> #include <cstdio> using namespace std; typedef long long ll; int m,num; deque<int> s1,s2; deque<int>::iterator it; ll read() { ll x=0,f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; return x*f; } int main() { ll n=read()+1;//以為空串也是好串,所以這裏要加一 for(ll i=1;i<=n;i<<=1)m++; for(int i=m-2;~i;i--) {//初始有一個空串是好串,m-2是n的第二高的二進制位 s1.push_back(++num),s2.push_back(num); if((n>>i)&1)s1.push_front(++num),s2.push_back(num); } printf("%d\n",(int)(s1.size()+s2.size())); for(it=s1.begin();it!=s1.end();it++) printf("%d ",(*it)); for(it=s2.begin();it!=s2.end();it++) printf("%d ",(*it)); return 0; }
AtCoder Grand Contest 012 C:Tautonym Puzzle