jzoj 5113 【usaco2017_Mar Platinum】COWBASIC

来源:互联网 发布:金牛软件官网 编辑:程序博客网 时间:2024/05/29 08:01

写一个解释器,支持

Input
You are given a COWBASIC program at most 100 lines long, with each line being at most 350 characters long. A COWBASIC program is a list of statements.
There are three types of statements:
< variable > = < expression >
< literal> MOO {
< list of statements>
}
RETURN < variable>
There are three types of expressions:
< literal>
< variable>
( < expression> ) + ( < expression> )
A literal is a positive integer at most 100,000.
A variable is a string of at most 10 lowercase English letters.
It is guaranteed that no variable will be used or RETURNed before it is defined. It is guaranteed that RETURN will happen exactly once, on the last line of the program.

分析

只有加法运算,循环语句。

不难整理出循环内每一次变量的变化方式(系数*变量),那么就可以暴力做。
考虑到循环次数直接模拟会超限,然后变化方式是线性变换,所以可以采用矩阵乘法加速。

对于每一个循环,算出一个友矩阵。然后将上层当前友矩阵乘上当前友矩阵循环次数次方。
注意友矩阵的意义应该是原a,b,c到新a,b,c的变化,所以每进入一个新循环,友矩阵应该设为元矩阵。
然后对于赋值语句a=a+b要将a,b拆成当前系数叠加到a中,而不是直接将a的a,b系数设为1,比如说:

a = b + 1 //这时a的系数为{0,1,0} -> {1,0,1}
b= a //这时c的系数为{0,1,0} -> {1,0,1},将当前a的系数代入而不是直接将a这个地方设为1。

实现

#include <cstdio> #include <iostream> #include <cstring>#define maxn 110#define mo 1000000007lltypedef long long ll;typedef ll Expre[maxn];typedef ll Mat[maxn][maxn];using namespace std;char s[500];char t[20];char vars[maxn][11];ll mi[maxn];Mat f[maxn];ll point,tot,len,vtot;void getName(char *name) {    memset(name,0,11);    ll lent=0;    while (s[point]!=' ')         name[++lent]=s[point++];}ll getNum() {    ll ret=0;    while (s[point]!=' ') ret=ret*10+s[point++]-'0';    return ret;}ll getVar(const char *name) {    for (ll i=1; i<=vtot; i++) {        ll suc=1;        for (ll j=1; j<=10; j++)             if (name[j]!=vars[i][j]) {suc=0;break;}        if (suc) return i;    }    return 0;}char t2[20];void getExpre(Expre c) {    for (; point<len;) {        while (( s[point]==' ' || s[point]=='(' || s[point]==')' || s[point]=='+' || s[point]=='=') && point<len) point++;        if (point==len) break;        if (isdigit( s[point] )) c[0]=( c[0]+getNum() )%mo; else {            getName(t2);            ll k=getVar(t2);            for (ll i=0; i<=vtot; i++) c[i]=(c[i]+f[tot][i][k])%mo;        }    }}void set(ll k,Expre ex) {    for (ll i=0; i<=vtot; i++) f[tot][i][k]=ex[i];}Mat rez2;void mult(const Mat a,const Mat b) {    memset(rez2,0,sizeof rez2);    for (ll i=0; i<=vtot; i++)         for (ll j=0; j<=vtot; j++)             for (ll z=0; z<=vtot; z++) {                rez2[i][j]=(rez2[i][j]+a[i][z]*b[z][j])%mo;            }}Mat rez;void quickPower(const Mat a,ll y) {    if (y==1) {        memcpy(rez,a,sizeof rez);        return;    }    quickPower(a,y/2);    mult(rez,rez);    memcpy(rez,rez2,sizeof rez);    if (y&1==1) {        mult(rez,a);        memcpy(rez,rez2,sizeof rez);    }}ll readStr() {    memset(s,0,sizeof s);    char c; point=0;    while (scanf("%c",&c),c!='\n') s[++point]=c;    len=point;    return 0;}Expre e;int main() {    //freopen("cowbasic.in","r",stdin);    freopen("cb.in","r",stdin);    //freopen("cowbasic.out","w",stdout);    tot=0;    f[0][0][0]=1;    while (readStr()==0) {        point=1;        while (s[point]==' ') point++;        s[++len]=' ';        if (s[point]=='R') {            point+=7; getName(t);            //printf("%d\n",getVar(t));            printf("%d\n",f[tot][0][getVar(t)]);            return 0;        }        if (s[point]>='a' && s[point]<='z') {            getName(t);            memset(e,0,sizeof e);  getExpre(e);            ll k=getVar(t);            if (k==0)  {                //printf("%lld %s\n",vtot+1,t+1);                memcpy(vars[++vtot],t,11);                for (int i=0; i<tot; i++) f[i][vtot][vtot]=1;                set(vtot,e);            } else set(k,e);            continue;        }        if (isdigit(s[point])) { //MOO BEGIN             mi[++tot]=getNum();            memset(f[tot],0,sizeof f[tot]);            for (ll i=0; i<=vtot; i++) f[tot][i][i]=1;            continue;        }        if (s[point]=='}') { //MOO EN            quickPower(f[tot],mi[tot]);            memcpy(f[tot],rez,sizeof rez);            mult(f[tot-1],f[tot]);            memcpy(f[tot-1],rez2,sizeof f[tot-1]);            tot--;        }    }}
1 0
原创粉丝点击