題目連結:http://codeforces.com/contest/897/problem/C
題意:
給你一些字串:
A: [What are you doing at the end of the world? Are you busy? Will you save us?]
B: [What are you doing while sending "]
C: ["? Are you busy? Will you send "]
D: ["?]
(中括號內為給出的字串,問號、引號、空格也算在內)
定義字串f[0] = A,遞推式f[n] = B + f[n-1] + C + f[n-1] + D
比如:
f[0] = [What are you doing at the end of the world? Are you busy? Will you save us?]
f[1] = [What are you doing while sending "What are you doing at the end of the world? Are you busy? Will you save us?"? Are you busy? Will you send "What are you doing at the end of the world? Are you busy? Will you save us?"?]
然後有q個詢問,每個詢問有兩個整數n,k,讓你輸出f[n]的第k個字元。如果f[n]沒有第k個字元,則輸出'.'。
題解:
定義la,lb,lc,ld分別代表字串A,B,C,D的長度:
la=75, lb=34, lc=32, ld=2
定義len[i]為字串f[i]的長度,很容易推出len[i] = (2^i)*la + (2^i - 1)*(lb + lc + ld)。
因為len[i]有可能很大,而k只有10^18,所以當i>=54的時候,直接返回一個很大的數就行了(比如9e18)。
對於每個詢問,先判斷是否k >= len[n]。如果是,直接輸出'.'。
否則就從後往前推位置。
因為f[n] = B + f[n-1] + C + f[n-1] + D
所以當前位置k在f[n]中的位置有5種情況:
(1)k在B中,即k∈[1, lb]
(2)k在第一個f[n-1]中,即k∈[lb+1, lb+len[n-1]]
(3)k在C中,即k∈[lb+len[n-1]+1, lb+len[n-1]+lc]
(4)k在第二個f[n-1]中,即k∈[lb+len[n-1]+lc+1, lb+len[n-1]*2+lc]
(5)k在D中,即k∈[lb+len[n-1]*2+lc+1, lb+len[n-1]*2+lc+ld]
對於情況1,3,5,找到k在B,C,D中對應的位置,輸出即可:
(1)k不變
(3)k -= lb+len[n-1]
(5)k -= lb+len[n-1]*2+lc
對於情況2,4,將k變成在f[n-1]中的位置,繼續執行這種變換即可。
(2)k -= lb
(4)k -= lb+len[n-1]+lc
最多變換n次,所以總複雜度為O(qn)。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 5 using namespace std; 6 7 long long n,k,q; 8 long long la=75,lb=34,lc=32,ld=2; 9 string a=" What are you doing at the end of the world? Are you busy? Will you save us?"; 10 string b=" What are you doing while sending \""; 11 string c=" \"? Are you busy? Will you send \""; 12 string d=" \"?"; 13 string s; 14 15 long long len(long long i) 16 { 17 if(i>=54) return 9000000000000000000LL; 18 return ((1LL<<i)-1LL)*(la+lb+lc+ld)+la; 19 } 20 21 inline bool cont(long long x,long long l,long long r) 22 { 23 return l<=x && x<=r; 24 } 25 26 int main() 27 { 28 cin>>q; 29 while(q--) 30 { 31 cin>>n>>k; 32 if(k>len(n)) 33 { 34 s+="."; 35 continue; 36 } 37 long long form=1; 38 for(long long i=n;i>=1;i--) 39 { 40 long long temp=len(i-1); 41 bool flag=false; 42 if(cont(k,1,lb)) form=2,flag=true; 43 if(cont(k,lb+temp+1,lb+temp+lc)) k-=lb+temp,form=3,flag=true; 44 if(cont(k,lb+temp*2+lc+1,lb+temp*2+lc+ld)) k-=lb+temp*2+lc,form=4,flag=true; 45 if(flag) break; 46 if(cont(k,lb+1,lb+temp)) k-=lb; 47 if(cont(k,lb+temp+lc+1,lb+temp*2+lc)) k-=lb+temp+lc; 48 } 49 if(form==1) s+=a[k]; 50 if(form==2) s+=b[k]; 51 if(form==3) s+=c[k]; 52 if(form==4) s+=d[k]; 53 } 54 cout<<s<<endl; 55 }