zoukankan      html  css  js  c++  java
  • 一类求第K大,第K个问题的方法

    CF768B

    题目链接:

    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 nlr (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

    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]='';
    60     }
    61         printf("%s
    ",ans);
    62     return 0;
    63 }
    896A

    题目链接:

      http://acm.timus.ru/problem.aspx?space=1&num=1081 

    题意:

    Consider all the sequences with length (0 < N < 44), containing only the elements 0 and 1, and no two ones are adjacent (110 is not a valid sequence of length 3, 0101 is a valid sequence of length 4). Write a program which finds the sequence, which is on K-th place (0 < K < 109) in the lexicographically sorted in ascending order collection of the described sequences.

    Input

    The first line of input contains two positive integers N and K.

    Output

    Write the found sequence or −1 if the number K is larger then the number of valid sequences.

    Sample

    inputoutput
    3 1
    
    000
    

     

    分析:

    求第K小的字符串。

    我们假设dp[i][0]:为以0开头的长度为i的合法串的个数,dp[i][1]:为以1开头的长度为i的个数。

    所以有dp[1][0]=1,dp[1][1]=1;

    dp[i+1][1]=dp[i][0];

    dp[i+1][0]=dp[i][1]+dp[i][0];

     然后也是一样的思想,就可以做了。

    代码:

     1 #include<cstdio>
     2 long long dp[50][2];
     3 int main(){
     4     int N,K;
     5     scanf("%d%d",&N,&K);
     6     dp[1][0]=1;dp[1][1]=1;
     7     for(int i=1;i<N;++i){
     8         dp[i+1][1]=dp[i][0];
     9         dp[i+1][0]=dp[i][0]+dp[i][1];
    10     }
    11     /*for(int i=1;i<=N;++i){
    12         printf("dp[%d][1]=%lld    ",i,dp[i][1]);
    13         printf("dp[%d][0]=%lld
    ",i,dp[i][0]);
    14     }*/
    15     if(K>dp[N][1]+dp[N][0]){
    16         printf("-1
    ");
    17         return 0;
    18     }
    19     for(int i=N;i>=1;--i){
    20         if(K<=dp[i][0]){
    21             printf("0");
    22 
    23         }else{
    24             printf("1");
    25             K-=dp[i][0];
    26         }
    27     }
    28     printf("
    ");
    29     return 0;
    30 }
    ural1081
  • 相关阅读:
    一篇文章搞明白CORS跨域
    我从来不理解JavaScript闭包,直到有人这样向我解释它...
    将博客搬至CSDN
    Spring Boot缓存源码分析
    网站技术架构
    在springboot中使用Mybatis Generator的两种方式
    官方文档Core Technologies
    Java诊断工具Arthas
    Intellij IDEA 修改代码后自动编译更新
    TabHost选项卡的实现(二):使用Fragment实现
  • 原文地址:https://www.cnblogs.com/sun-yinkai/p/7826108.html
Copyright © 2011-2022 走看看