ZOJ 3952 Fibonacci Sequence Chicken Edition(构造/模拟)

题意

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值