Algorithm 动态规划,第n个字符串

Algorithm 动态规划,第n个字符串,algorithm,dynamic-programming,Algorithm,Dynamic Programming,如何解决这个问题 数字序列中的第一个数字是1。通过对第(i-1)个数字应用以下操作来构造序列的每个后续第i个数字: 将1替换为114 将4替换为1 因此,顺序如下: 114114114114114114111141114 写一个程序来查找一个数字,这个数字是这个序列中第i个数字的第j位。如果第i个数字少于j位,则打印-1 输入格式 第一行:T(测试用例数) 每个测试用例中的第一行:两个空格分隔的整数i和j 输出格式 对于每个测试用例,打印一个数字,该数字是此序列中第i个数字的第j位。如果

如何解决这个问题

数字序列中的第一个数字是1。通过对第(i-1)个数字应用以下操作来构造序列的每个后续第i个数字:

  • 将1替换为114
  • 将4替换为1
因此,顺序如下:

114114114114114114111141114

写一个程序来查找一个数字,这个数字是这个序列中第i个数字的第j位。如果第i个数字少于j位,则打印-1

输入格式

  • 第一行:T(测试用例数)
  • 每个测试用例中的第一行:两个空格分隔的整数i和j
输出格式

对于每个测试用例,打印一个数字,该数字是此序列中第i个数字的第j位。如果第i个数字少于j位,则打印-1

约束


1让我们看看序列及其长度

114
3
114 114 1
7
114 114 1 114 114 1 114
    7         7      3
   773       773     7
773 773 7 773 773 7 773
...
每个长度是前一个序列的两倍,前一个序列与前一个序列相连,也称为:

length(i) =
  2 * length(i - 1) + length(i - 2)
给定最后一个字符串中的一个位置,因为我们知道前面的序列长度,我们可以在(1)加倍的前一个序列的第一个序列,(2)加倍的前一个序列的第二个序列,或者(3)附加的,从第二到最后的序列中确定它的长度

通过跟踪它的位置,我们不断地将它的位置转换为前面序列中的位置,直到我们到达第一个位置

例如:

    7         7      3
114 114 1 114 114 1 114
                  ^
我们知道前两个序列的长度分别为7和3,所以我们可以确定我们位于第二个7长度序列的第7个索引上。现在我们继续:

114 114 1
        ^
前两个序列的长度分别为3和1,因此我们处于倒数第二个序列(长度为1的序列)的第一个索引上


结果:1

根据•㪞דברקן的回答,以下是Java代码:

private static void getDigit( int n, long k ) {
    long[] L = new long[n+1];
    L[1] = 1;
    L[2] = 3;
    long MAX = Long.parseUnsignedLong("1000000000000");
    for ( int i = 3; i <= n; i++ ) {
      L[i] = 2*L[i-1] + L[i-2];
      if ( L[i] >= MAX ) break;
    }

    Long k1 = Long.valueOf(k);
    String s = "114";
    while ( n > 2 ) {
      if ( k1 <= L[n-1] ) {
          n--;
      } else if ( k1 > L[n-1] && k1 <= 2*L[n-1] ) {
        k1 = k1 - L[n-1];
        n--;
      } else {
        k1 = k1 - 2*L[n-1];
        n = n - 2;
      }
    }
    System.out.println( String.valueOf( s.charAt(k1.intValue()-1)));
}
private static void getDigit(int n,long k){
long[]L=新长[n+1];
L[1]=1;
L[2]=3;
long MAX=long.parseUnsignedLong(“10000000000”);
对于(int i=3;i=MAX)中断;
}
长k1=长数值(k);
字符串s=“114”;
而(n>2){

if(k1-L[n-1]&&k1链接会随着时间的推移而消失。在这里说明问题,而不是你的第三方链接。现在问题已经解决了。我已经在这里说明了整个问题。根据你的算法,似乎你需要一个长度可能为10^6的数组,因为你需要它们回溯以找到正确的位置?@SomeDude似乎是这样。好的。我无法想象除非能消耗更多10^12量级的空间,否则更有效的方法。
114 114 1
        ^
private static void getDigit( int n, long k ) {
    long[] L = new long[n+1];
    L[1] = 1;
    L[2] = 3;
    long MAX = Long.parseUnsignedLong("1000000000000");
    for ( int i = 3; i <= n; i++ ) {
      L[i] = 2*L[i-1] + L[i-2];
      if ( L[i] >= MAX ) break;
    }

    Long k1 = Long.valueOf(k);
    String s = "114";
    while ( n > 2 ) {
      if ( k1 <= L[n-1] ) {
          n--;
      } else if ( k1 > L[n-1] && k1 <= 2*L[n-1] ) {
        k1 = k1 - L[n-1];
        n--;
      } else {
        k1 = k1 - 2*L[n-1];
        n = n - 2;
      }
    }
    System.out.println( String.valueOf( s.charAt(k1.intValue()-1)));
}