您的位置:首页 > 其它

[表达式求值 矩阵乘法] ZROI 2017提高10A. Calc

2017-11-04 16:18 330 查看
神思路,第一次见到这种操作…

构造矩阵来进行状态的转移。

A+B∗C ,我们记3元组 (S,M,T) 表示当前状态,其中S=A, M=B, T=B∗C。

这样记录,每多一个字符,转移可以表示成乘上一个矩阵。

数字 k : (S,M,T)→(S,M,T∗10+M∗k)

+ : (S,M,T)→(S+T,1,0)

− : (S,M,T)→(S,T,0)

矩阵快速幂优化。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=100005,MOD=998244353;
struct Matrix{
int n,m,a[5][5];
Matrix(int x=0){ memset(a,0,sizeof(a)); a[0][0]=a[1][1]=a[2][2]=a[3][3]=x; }
Matrix operator * (const Matrix &b)const{
Matrix c; c.n=n; c.m=b.m;
for(int i=0;i<=c.n-1;i++)
for(int j=0;j<=c.m-1;j++)
for(int k=0;k<=m-1;k++)
(c.a[i][j]+=(LL)a[i][k]*b.a[k][j]%MOD)%=MOD;
return c;
}
} ans;
int n;
Matrix getM(char ch){
Matrix c; c.n=c.m=4;
if(ch=='+') c.a[0][0]=c.a[2][0]=c.a[3][1]=c.a[3][3]=1; else
if(ch=='*') c.a[0][0]=c.a[2][1]=c.a[3][3]=1; else
c.a[0][0]=c.a[1][1]=c.a[3][3]=1, c.a[2][2]=10, c.a[1][2]=ch-'0';
return c;
}
char st[20];
Matrix Pow(Matrix a,int b){
Matrix res=1; res.n=res.m=4;
for(;b;b>>=1,a=a*a) if(b&1) res=res*a;
return res;
}
int main(){
freopen("zroi10A.in","r",stdin);
freopen("zroi10A.out","w",stdout);
scanf("%d",&n);
ans=0; ans.n=1; ans.m=4; ans.a[0][1]=ans.a[0][3]=1;
for(int i=1;i<=n;i++){
int x; scanf("%d%s",&x,st+1); int len=strlen(st+1);
Matrix res=1; res.n=res.m=4;
for(int i=1;i<=len;i++) res=res*getM(st[i]);
ans=ans*Pow(res,x);
}
ans=ans*getM('+');
printf("%d\n",ans.a[0][0]);
return 0;
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: