题意
chicken,chicken,chiken…
思路
题目要求用小叽叽写出一个能计算斐波那契第n项的程序,有一个解析器会执行我们的程序,程序的输出就是程序结束时的栈顶元素。
由于程序并没有提供循环/判断的语句,也没有输出的语句,所以我们只能利用copy将元素弄到栈顶,然后结束程序进行输出。
前30项存储斐波那契的值,31-34是缓冲区,存储操作数与被操作值,计算出斐波那契数后复制到相应位置,输出就是相反操作,具体见代码的调试模式。
代码
如果这题像cf一样直接提供parser多好,这样检查比较方便
不过没关系,大不了自己写一个parser。。
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define sc(a) scanf("%d",&a)
const int INF=0x3f3f3f3f;
const int maxn=2e5+50;
const int mod=1e9+7;
const double eps=1e-8;
#define pii pair<int,int>
typedef long long ll;
typedef unsigned int ui;
using namespace std;
int fib[31];
void initFib(){
fib[1]=fib[2]=1;
rep(i,3,31) fib[i]=fib[i-1]+fib[i-2];
}
struct Parser{
int stk[233];
int pos;
queue<int> inputs;
void push(int x){
stk[pos++]=x;
}
bool empty(){
return pos==0;
}
int size(){
return pos;
}
int top(){
return stk[pos-1];
}
void pop(){
pos--;
}
Parser(const queue<int> &inputs) : inputs(inputs) {pos=0;}
void ERROR(){
puts("ERROR");
exit(-1);
}
void work(int operand){
if(operand>=7) {
push(operand-7);
return;
}
int x,y;
switch (operand){
case 1:
if(size()<2) ERROR();
x=top(); pop();
y=top(); pop();
push(x+y);
break;
case 2:
if(size()<2) ERROR();
x=top(); pop();
y=top(); pop();
push(x-y);
break;
case 3:
if(size()<2) ERROR();
x=top(); pop();
y=top(); pop();
push(x==y);
break;
case 4:
if(inputs.empty()) ERROR();
push(inputs.front());
inputs.pop();
break;
case 5:
if(size()<2) ERROR();
x=top(); pop();
y=top(); pop();
stk[x-1]=stk[y-1];
if(x>pos) {
printf("pos %d x %d OL\n",pos,x);
ERROR();
}
break;
}
}
int stop(){
if(empty()) {
ERROR();
}
return top();
}
void printStack(){
printf("stack is ");
rep(i,0,pos) printf("%02d ",stk[i]);
puts("= =");
}
};
vector<string> ans;
inline void pb(string s){
ans.push_back(s);
}
inline string push(int x){
return string(x+7,'c');
}
inline string getOp(int x){
return string(x,'c');
}
inline void copyFrom(int from,int to){
pb(push(from));
pb(push(to));
pb(getOp(5));
}
inline void readN(){
pb(getOp(4));
}
inline void add(){
pb(getOp(1));
}
void work(){
ans.clear();
rep(i,0,30) pb(push(1));
// cal fib(3) to 30
rep(i,3,31){
//safety buf
if(i==3) pb(push(0));
pb(push(0));
copyFrom(i-2,31);
copyFrom(i-1,32);
add();
copyFrom(31,i);
}
readN();
pb(push(31));
pb(getOp(5));
}
void check(int n){
work();
queue<int> v;
v.push(n);
Parser parser(v);
parser.inputs=v;
for(int i=0;i<ans.size();i++) {
string op=ans[i];
int sz=op.length();
printf("op %d ",sz);
if(sz==5) puts("copy");
else if(sz==4) puts("read");
else if(sz>=7) printf("push %d\n",sz-7);
else if(sz==1) puts("add");
parser.work(sz);
parser.printStack();
}
printf("%d %d\n",parser.stop(),fib[n]);
}
int main()
{
#ifndef ONLINE_JUDGE
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
bool debug=false;
if(debug){
initFib();
int n;
while(cin>>n){
check(n);
}
}else{
work();
for(int i=0;i<ans.size();i++) cout<<ans[i]<<endl;
}
return 0;
}