题目链接:
http://codeforces.com/problemset/problem/768/B
题目:
Initially Sam has a list with a single element n. Then he has to perform certain operations on this list. In each operation Sam must remove any element x, such that x > 1, from the list and insert at the same position , , sequentially. He must continue with these operations until all the elements in the list are either 0 or 1.
Now the masters want the total number of 1s in the range l to r (1-indexed). Sam wants to become a maester but unfortunately he cannot solve this problem. Can you help Sam to pass the eligibility test?
The first line contains three integers n, l, r (0 ≤ n < 2^50, 0 ≤ r - l ≤ 10^5, r ≥ 1, l ≥ 1) – initial element and the range lto r.
It is guaranteed that r is not greater than the length of the final list.
Output the total number of 1s in the range l to r in the final sequence.
分析:
非常有趣的一道题,就是说我们有一个数n我们把它打散为一串0,1序列,方式如上所述,问l到r中有多少个1。
打散方式:比如说7,。
先通过找规律我们可以发现以下两条结论:
1,数x打散后的序列中有x个1。
2,数x打散后的序列有 2n-1位数,其中2n-1为刚好大于等于x的数。
现在给你l,r,问从第l位到第r位有多少个1.
那么这个问题,我们就可以转化为第x位以前有多少个1,然后再相减,就是答案了。
我们可以采用线段树的思想,
这样我们就可以利用第2条确定向左走还是向右走,第1条来确定有多少个1了。
题目链接:
http://codeforces.com/contest/896/problem/A
题目:
s0 = "What are you doing at the end of the world? Are you busy? Will you save us?".
si = "What are you doing while sending "si - 1"? Are you busy? Will you send "si - 1"?" ( i ≥ 1)
给你一个n(n<=105)和k(k<=1018),问你在fn中第k个字符是什么,如果没有就输出 '.'。
分析:
我们可以算出每个fi包含多少个字符。我们算出来:
f0=75
fn=34+fn-1+32+fn-1+2(n>=1)
我们还是利用到与上面一个类似的思想就可以做。
但要注意n特别大的时候的讨论,当时RE了好几发。
代码:
1 // 很重要!!hack点n>tot 2 #include<bits/stdc++.h> 3 using namespace std; 4 long long f[100]; 5 int tot=0; 6 char s[4][100]={ 7 "What are you doing while sending "", 8 ""? Are you busy? Will you send "", 9 ""?" 10 }; 11 char s1[100]="What are you doing at the end of the world? Are you busy? Will you save us?"; 12 void init(){ 13 /*for(int i=0;i<3;++i){ 14 int len=strlen(s[i]); 15 printf("len%d=%d ",i,len); 16 }*/ 17 //printf("len:%d ",strlen(s1)); 18 f[0]=75; 19 for(int i=1;;++i){ 20 f[i]=2*f[i-1]+68; 21 tot=i; 22 if(f[i]>1e18)break; 23 } 24 //printf("f[tot]=%lld ",f[tot]); 25 } 26 char ans[20]; 27 int cnt=0; 28 int main(){ 29 init(); 30 int q;scanf("%d",&q); 31 while(q--){ 32 int n;long long k; 33 scanf("%d%lld",&n,&k); 34 if(n>=tot||k<=f[n]){ 35 while(1){ 36 if(n==0){ 37 ans[cnt++]=s1[k-1]; 38 break; 39 } 40 if(k<=34){ 41 ans[cnt++]=s[0][k-1]; 42 break; 43 }else if((k-=34)&&(n>tot||k<=f[n-1])){ 44 n--; 45 }else if((k-=f[n-1])&&k<=32){ 46 ans[cnt++]=s[1][k-1]; 47 break; 48 }else if((k-=32)&&k<=f[n-1]){ 49 n--; 50 }else if((k-=f[n-1])){ 51 ans[cnt++]=s[2][k-1]; 52 break; 53 } 54 } 55 56 }else{ 57 ans[cnt++]='.'; 58 } 59 ans[cnt+1]='