题目描述
大数学家高斯小时候偶然间发现一种有趣的自然数集合Blash,对应以 a 为基的集合 Ba 定义如下:
(1)a是集合Ba的基,且a是Ba的第一个元素。
(2)如果×在集合Ba中,则2x+1和3x+1也都在集合Ba中。
(3)没有其他元素在集合Ba中了。
现在小高斯想知道如果将集合Ba中元素按照升序排列,第n个元素会是多少?
输入
一行输入包括两个数字,集合的基a以及所求元素序号n。((1<=a<=50,1<=n<=100000)
输出
第n个元素的值
样例
Sample Input : 1 100
Sample Output : 418
代码
思路一
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,p2,p3,a[N];
int main()
{
ios::sync_with_stdio(false);
cin>>a[1]>>n;
p2=1,p3=1;
for(int i=2;i<=n;i++)
{
a[i]=min(2*a[p2]+1,3*a[p3]+1);
if(a[i]==2*a[p2]+1)p2++;
if(a[i]==3*a[p3]+1)p3++;
}
printf("%d\n",a[n]);
return 0;
}
// 网上看到的思路
思路二
自己的思路:运用了一个栈s
用来存储Blash
集合,用队列q1
存储栈中数的2x+1
,q2
来存放栈中元素的3x+1
。 起初将a
压栈,作为栈中的第一个元素。此后进行n-1
轮循环,在每一轮循环中,取出栈首的元素x
,然后将2x+1
放入队列q1
,将3x+1
放入队列q2
。接下来中分别比较两个队列队首的元素,将较小的一方放入栈中,同时将该元素从相应的队列中pop
掉。
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,n;
ios::sync_with_stdio(false); // 加速输入输出,即cin和cout
stack<int> s;
queue<int> q1,q2;
cin>>a>>n;
s.push(a);
int num = n-1;
while(num--){ //起初s中已有一个元素,若选择n那么结束时s中将会有n+1个数
int top = s.top();
q1.push(top*2+1);
q2.push(top*3+1);
int front1 = q1.front();
int front2 = q2.front();
if(front1>front2){
s.push(front2);
q2.pop();
}
else if(front1<front2){
s.push(front1);
q1.pop();
}
else{ //栈的数中不允许重复
s.push(front1);
q1.pop();
q2.pop();
}
}
/*while(!s.empty()){
cout<<s.top()<<" ";
s.pop();
}*/
cout<<s.top()<<endl;
return 0;
}