1 条题解
-
0
自动搬运
来自洛谷,原作者为

zhzh2001
**搬运于
2025-08-24 21:51:24,当前版本为作者最后更新于2017-05-09 20:06:17,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题解
初看这道题感觉十分难做,除了麻烦的语法分析,还需要优化循环。
循环不嵌套
此时直接模拟即可,最多只有50个循环。
只有一个变量
当只有一个变量的时候,可以得到一个通项公式,但实际并不实用。具体可参考官方题解。
使用矩阵乘法
理论上,通过公式也可以做这道题,但是用矩阵乘法更加简洁。
构造转移矩阵
矩阵中包含各个变量的转移关系。对于矩阵A和B,先后执行等价于乘以A*B。而A循环n次则等价于乘以。
对于
nsq = ( nsq ) + ( ( n ) + ( ( n ) + ( 1 ) ) ),构造矩阵为1 n nsq 1 1 n 1 nsq 1 2 1注意转移没有被赋值的量。
另外,直接忽略表达式中的括号,因为加法没有优先级问题。
处理嵌套循环
维护一个栈,保存每层循环的结果和循环次数。
有新循环时,压入一个单位矩阵;循环退出时,弹出栈顶,执行快速幂,并与下一层相乘。
时间复杂度
矩阵大小不超过100x100,最多有50个循环,每个循环最多计算次矩阵乘法。实际上运算量不到1亿,可以轻松通过。
代码
#include<bits/stdc++.h> using namespace std; const int N=105,MOD=1e9+7; int n,cnt[N]; //cnt[]保存每层循环的次数 struct matrix { long long mat[N][N]; matrix() { memset(mat,0,sizeof(mat)); } matrix operator*(const matrix& rhs)const { matrix ans; for(int i=1;i<=n;i++) for(int k=1;k<=n;k++) for(int j=1;j<=n;j++) { ans.mat[i][j]=(ans.mat[i][j]+mat[i][k]*rhs.mat[k][j])%MOD; assert(ans.mat[i][j]>=0); } return ans; } matrix operator*=(const matrix& rhs) { return *this=*this*rhs; } }S[N]; //矩阵栈 matrix I() { matrix ans; for(int i=1;i<=n;i++) ans.mat[i][i]=1; return ans; } //单位矩阵 matrix qpow(matrix a,int b) { matrix ans=I(); do { if(b&1) ans*=a; a*=a; } while(b/=2); return ans; } //矩阵快速幂 string code[N]; template<typename T> inline T get_token(const string& s) { stringstream ss(s); T ret; ss>>ret; return ret; } //将字符串s中的下一个内容转换为T int main() { map<string,int> var; //保存变量名对应的编号 var["1"]=1; //没什么用 int lines=0; n=1; while(getline(cin,code[++lines])) if(code[lines].find('=')!=string::npos) { string name=get_token<string>(code[lines]); //题目保证所有变量都会为左值 if(var.find(name)==var.end()) var[name]=++n; } lines--; int sp=1; S[sp]=I(); for(int i=1;i<=lines;i++) if(code[i].substr(0,6)=="RETURN") cout<<S[sp].mat[var[get_token<string>(code[i].substr(6))]][1]<<endl; //运算结果保存在矩阵第一列中 else if(code[i].find("MOO")!=string::npos) //新循环 { S[++sp]=I(); cnt[sp]=get_token<int>(code[i]); } else if(code[i].find('}')!=string::npos) //循环结束 { S[sp-1]=qpow(S[sp],cnt[sp])*S[sp-1]; sp--; } else { matrix now; int row=var[get_token<string>(code[i])],p=code[i].find('=')+1; stringstream ss(code[i].substr(p)); string token; while(ss>>token) { if(isdigit(token[0])) now.mat[row][1]+=get_token<int>(token); //累加常数 else if(isalpha(token[0])) now.mat[row][var[token]]++; //累加变量 } for(int i=1;i<=n;i++) if(i!=row) now.mat[i][i]=1; //转移未赋值的量 S[sp]=now*S[sp]; } return 0; }语法分析时应该充分利用空格,同时也要防止多余的空格。
- 1
信息
- ID
- 1129
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者