链接:洛谷P3666
一看到这道题,很容易想到模拟,但是循环最多有 49 49 层,每层都可能要循环 105 10 5 次,总的就要 10245 10 245 次,显然是通过不了的。
换个思路,我们也可能可以得到通项公式,但是计算难度有些大,像我这样的蒟蒻是永远也推不出来的。
这时我们来考虑矩阵乘法,思路一下就明朗了,我们把字符串解析一遍,建出一棵树,剩下来的全可以靠矩乘搞定啦!
于是这题就变成了一道码农题。。。
不说了,再来算一下复杂度,最坏情况要做 993×98 99 3 × 98 次,还是可以通过的,但在洛谷上得开 O2 O 2 。。。
蒟蒻的跑得奇慢无比的代码:
#pragma GCC optimize("O3")
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
const int md=1e9+7;
string buf;
string str[400];
int n;
map<string,int>mp;
struct mat{
int a[110][110];
int h,w;
mat(){memset(a,0,sizeof(a));h=w=0;}
mat operator*(mat u)const
{
mat res;
res.h=h;res.w=u.w;
for(int i=1;i<=h;i++)
{
for(int j=1;j<=u.w;j++)
{
for(int k=1;k<=w;k++)
{
res.a[i][j]+=1LL*a[i][k]*u.a[k][j]%md;
if(res.a[i][j]>=md)res.a[i][j]-=md;
}
}
}
return res;
}
void operator*=(mat u)
{
*this=*this*u;
}
};
void skip(string s,int &p)
{
while(p<s.size() && s[p]==' ')p++;
}
void rskip(string s,int &p)
{
while(p>=0 && s[p]==' ')p--;
}
string getstr(string s,int &p)
{
skip(s,p);
string res="";
while(p<s.size() && s[p]!=' ')res+=s[p++];
skip(s,p);
return res;
}
int getval(string s)
{
int res=0;
for(int i=0;i<s.size();i++)
{
if(!isdigit(s[i]))return -1;
res=res*10+s[i]-'0';
}
return res;
}
mat matrix[400];
int times[400];
vector<int>G[400];
int tot,cnt;
mat qmul(mat x,int p)
{
mat res;
res.h=x.h;
res.w=x.w;
for(int i=1;i<=res.h;i++)res.a[i][i]=1;
for(;p;p>>=1,x*=x)if(p&1)res*=x;
return res;
}
int dfs(int x,int p)
{
if(x>=n)return x;
int pos=(int)str[x].size()-1;
rskip(str[x],pos);
if(str[x][pos]=='}')return x;
tot++;
G[p].push_back(tot);
if(str[x][pos]=='{')
{
pos=0;
times[tot]=getval(getstr(str[x],pos));
x=dfs(x+1,tot);
}
else
{
int i=0;
int var=mp[getstr(str[x],i)];
matrix[tot].h=matrix[tot].w=cnt+1;
for(int i=1;i<var;i++)matrix[tot].a[i][i]=1;
for(int i=var+1;i<=cnt+1;i++)matrix[tot].a[i][i]=1;
for(;i<str[x].size();)
{
string tmp=getstr(str[x],i);
int val=getval(tmp);
if(val==-1)
{
if(tmp!="(" && tmp!=")" && tmp!="+" && tmp!="=")
{
matrix[tot].a[mp[tmp]][var]++;
}
}
else matrix[tot].a[cnt+1][var]+=val;
}
}
dfs(x+1,p);
}
mat solve(int x)
{
if(!G[x].size())return matrix[x];
matrix[x]=solve(G[x][0]);
for(int i=1;i<G[x].size();i++)matrix[x]*=solve(G[x][i]);
return matrix[x]=qmul(matrix[x],times[x]);
}
int main()
{
while(getline(cin,buf))
{
str[++n]=buf;
int pos=(int)buf.size()-1;
rskip(buf,pos);
if(buf[pos]=='{' || buf[pos]=='}')continue;
for(int i=0;i<buf.size();)
{
string tmp=getstr(buf,i);
if(getval(tmp)==-1)
{
if(tmp!="(" && tmp!=")" && tmp!="+" && tmp!="=" && tmp!="RETURN" && !mp[tmp])
{
mp[tmp]=++cnt;
}
}
}
}
times[0]=1;
dfs(1,0);
solve(0);
mat res;
res.h=1;
res.w=cnt+1;
res.a[1][cnt+1]=1;
mat tmp=solve(0);
res*=tmp;
int pos=0;
getstr(str[n],pos);
printf("%d",res.a[1][mp[getstr(str[n],pos)]]);
return 0;
}