如何解决问题https://www.hackerearth.com/problem/algorithm/special-numbers-39d71325/。
一个数字序列中的第一个数字是1。通过对第(i-1)个数字应用以下操作来构造序列中的每个第i个数字:
因此,顺序如下:
1,114,1141141,11411411141141114,...
编写一个程序以查找一个数字,该数字是此序列中第i个数字的第j个数字。如果第i个数字少于j个数字,则打印-1。
输入格式
输出格式
对于每个测试用例,按此顺序打印一个数字,该数字是第i个数字的第j个数字。如果第i个数字少于j个数字,则打印-1。
约束
1 <= T <= 10000(10等于4的幂)
1 <= i <= 1000000(10等于6的幂)
1 <= j <= 1000000000000(10等于12的幂)
Sample input Sample output
4
2 2 1
2 3 4
3 6 4
3 7 1
说明
第一个测试用例:序列中的第二个数字是114,第二个数字是1。
第二个测试用例:序列中的第二个数字为114,第三个数字为4。
第3个测试用例:序列中的第3个数字是1141141,第6个数字是4。
第4个测试用例:序列中的第3个数字是1141141,第7个(最后一个)数字是1。
将所有字符串(最多ith个字符串)存储在vector中将花费大量时间。问题的标记是记忆(动态编程)。我想要使用记忆(动态编程)的代码/策略。
我不认为我的以下方法更接近于实际/正确的解决方案。
在vector<string> v(15);
行之后查看注释
如果这是询问此类问题的平台,请告诉我在哪里提出此类问题。
#include<iostream>
#include<string>
#include<vector>
#include<cstring>
#include<climits>
//#define tr(v,it) for(typeof(v.begin()) it=v.begin();it!=v.end();it++)
using namespace std;
int main() {
vector<string> v(15);//v(14) runs under 1 sec even v(15) gives tle. So think how much time v(1000000) will take.
v[0]="1";
vector<string>::iterator it;
int n,h,i,j,tc;
string s,s1;
char ch='a';
for(it=v.begin()+1;it!=v.end();it++) {//set value
s=*(it-1); s1="";
for(unsigned int i=0;i<s.length();i++) {
char ch=s[i];
if(ch=='1') {
s1=s1+"114";
}
else {
s1=s1+'1';
}
}
*it=s1;
}
/*for(it=v.begin();it!=v.end();it++) {//print value
cout<<*it<<endl;
}
cin>>tc;
while(tc--) {
cin>>i>>j;
cout<<v[i-1][j-1];
}*/
return 0;
}
//谢谢!
答案 0 :(得分: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
...
每个长度是先前序列与之前序列(即AKA)的两倍。
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
答案 1 :(得分:0)
基于גלעדברקן的回答,这是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)));
}
您可以通过传递不同的n,k值here对其进行测试。