给你一个 \(n\times m\) 的字符网格 \(s\),\(s_{i,j}\in[1,9]\cup\{+,*\}\),从 \((1,1)\) 开始,仅向下或向右走并最终到达 \((n,m)\) 的路径被称为合法路径,求所有合法路径对应的表达式的运算结果之和,答案对 \(998244353\) 取模。 爆搜,枚举路径,直接算表达式值然后求和。 对于没有运算符的情况,容易观察到一个点对经过它的所有路径的贡献是相同的,而经过一个点有多少合法路径是经典问题,直接算就行。 观察一个表达式一定是由几个乘积项相加得来,即形如:\(a_1*a_2+a_3*a_4\) 的式子。应用数学定义:几个数相乘为一项,则表达式为一个多项式。考虑DP:设 \(dp_{i,j}\) 表示当前位置已经处理过的项的和,\(now_{i,j}\) 表示当前位置没有处理(即这个数字还没有结束)的数字之和,\(re_{i,j}\) 表示如果这里是数字,那么这个数字会被加几次。对于转移要分讨当前位置: 这个就比较显然了。对于不是 \(+\) 的情况,由于该项还没有结束,所以不会对 \(dp\) 数组产生额外贡献;对于是 \(+\) 的情况,该项结束,所以把之前没结束的答案累加。 对于运算符的情况就相当显然了,这个数结束了,所以赋值为 \(0\);对于数字的情况,此时 \(re\) 数组就派上用场了,这里的被累加几次是包括了之前乘积做的贡献的,所以直接乘就行。 对于 \(+\),之前的项直接结束,没有乘积贡献,所以初始化为经过次数;对于 \(*\),要乘上之前的数,所以累加 \(now\);对于数字,没有额外贡献,直接把之前乘积的贡献累加。 注意最终答案为 \(dp_{a,b}+now_{a,b}\)。注意阶乘要预处理到 \(n+m\)。A. 网格(grid)
题目内容
部分分
44pts
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ri register int
#define inf 0x3f3f3f3f
int a,b;
const int mod=998244353;
char c[2002][2002],d[4004];
long long ans;
il void check()
{
stack<int>num;
stack<char>op;
register long long rn=0;
for(ri i=1;i<=a+b-1;i++)
{
if(d[i]>='0'&&d[i]<='9')
{
rn=(rn*10+d[i]-'0')%mod;
}
else
{
if(!op.empty()&&op.top()=='*')
{
op.pop();
rn=(rn*num.top())%mod;
num.pop();
}
num.push(rn);
op.push(d[i]);
rn=0;
}
}
if(!op.empty()&&op.top()=='*')
{
op.pop();
rn=(rn*num.top())%mod;
num.pop();
}
num.push(rn);
rn=0;
while(!num.empty())
{
rn=(rn+num.top())%mod;
num.pop();
}
ans=(ans+rn)%mod;
}
void dfs(int x,int y)
{
d[x+y-1]=c[x][y];
if(x==a&&y==b)
{
check();
return;
}
if(x!=a)
{
dfs(x+1,y);
}
if(y!=b)
{
dfs(x,y+1);
}
}
int main()
{
freopen("grid.in","r",stdin);
freopen("grid.out","w",stdout);
scanf("%d%d",&a,&b);
for(ri i=1;i<=a;i++)
{
for(ri j=1;j<=b;j++)
{
scanf("%c",&c[i][j]);
if((c[i][j]<'0'||c[i][j]>'9')&&c[i][j]!='+'&&c[i][j]!='*')
{
j--;
}
}
}
dfs(1,1);
printf("%lld",ans);
return 0;
}
55pts
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ri register int
#define inf 0x3f3f3f3f
int a,b;
const int mod=998244353;
bool te1;
char c[2002][2002],d[4004];
long long ans,jc[4004],ny[4004],ten[4004];
void exgcd(int u,int v,long long &x,long long &y)
{
if(!v)
{
x=1;
y=0;
return;
}
exgcd(v,u%v,y,x);
y-=u/v*x;
}
il long long C(int x,int y)
{
return (((jc[x]*ny[x-y])%mod)*ny[y])%mod;
}
il void check()
{
stack<int>num;
stack<char>op;
register long long rn=0;
for(ri i=1;i<=a+b-1;i++)
{
if(d[i]>='0'&&d[i]<='9')
{
rn=(rn*10+d[i]-'0')%mod;
}
else
{
if(!op.empty()&&op.top()=='*')
{
op.pop();
rn=(rn*num.top())%mod;
num.pop();
}
num.push(rn);
op.push(d[i]);
rn=0;
}
}
if(!op.empty()&&op.top()=='*')
{
op.pop();
rn=(rn*num.top())%mod;
num.pop();
}
num.push(rn);
rn=0;
while(!num.empty())
{
rn=(rn+num.top())%mod;
num.pop();
}
ans=(ans+rn)%mod;
}
void dfs(int x,int y)
{
d[x+y-1]=c[x][y];
if(x==a&&y==b)
{
check();
return;
}
if(x!=a)
{
dfs(x+1,y);
}
if(y!=b)
{
dfs(x,y+1);
}
}
namespace task1
{
short main()
{
jc[0]=ny[0]=ten[0]=1;
for(ri i=1;i<=a+b;i++)
{
jc[i]=(jc[i-1]*i)%mod;
register long long j;
exgcd(jc[i],mod,ny[i],j);
while(ny[i]<0)
{
ny[i]+=mod;
}
ten[i]=(ten[i-1]*10)%mod;
}
for(ri i=1;i<=a;i++)
{
for(ri j=1;j<=b;j++)
{
register long long k=(C(i+j-2,i-1)*C(a+b-i-j,a-i))%mod;
k*=(ten[a+b-i-j]*(c[i][j]-'0'))%mod;
ans+=k%mod;
ans%=mod;
}
}
printf("%lld",ans);
return 0;
}
}
int main()
{
freopen("grid.in","r",stdin);
freopen("grid.out","w",stdout);
scanf("%d%d",&a,&b);
te1=true;
for(ri i=1;i<=a;i++)
{
for(ri j=1;j<=b;j++)
{
scanf("%c",&c[i][j]);
if((c[i][j]<'0'||c[i][j]>'9')&&c[i][j]!='+'&&c[i][j]!='*')
{
j--;
}
if(c[i][j]=='+'||c[i][j]=='*')
{
te1=false;
}
}
}
if(te1)
{
return task1::main();
}
dfs(1,1);
printf("%lld",ans);
return 0;
}
正解
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ri register int
#define inf 0x3f3f3f3f
int a,b;
const int mod=998244353;
char c[2002][2002];
long long dp[2002][2002],re[2002][2002],now[2002][2002],jc[4004],ny[4004];
void exgcd(int u,int v,long long &x,long long &y)
{
if(!v)
{
x=1;
y=0;
return;
}
exgcd(v,u%v,y,x);
y-=u/v*x;
}
il long long C(int x,int y)
{
return (((jc[x]*ny[x-y])%mod)*ny[y])%mod;
}
int main()
{
freopen("grid.in","r",stdin);
freopen("grid.out","w",stdout);
scanf("%d%d",&a,&b);
for(ri i=1;i<=a;i++)
{
for(ri j=1;j<=b;j++)
{
scanf("%c",&c[i][j]);
if((c[i][j]<'0'||c[i][j]>'9')&&c[i][j]!='+'&&c[i][j]!='*')
{
j--;
}
}
}
jc[0]=ny[0]=1;
for(ri i=1;i<=a+b;i++)
{
jc[i]=(jc[i-1]*i)%mod;
register long long j;
exgcd(jc[i],mod,ny[i],j);
while(ny[i]<0)
{
ny[i]+=mod;
}
}
re[0][1]=1;
for(ri i=1;i<=a;i++)
{
for(ri j=1;j<=b;j++)
{
switch(c[i][j])
{
case '+':
{
dp[i][j]=(dp[i-1][j]+dp[i][j-1]+now[i-1][j]+now[i][j-1])%mod;
re[i][j]=C(i+j-2,i-1);
now[i][j]=0;
break;
}
case '*':
{
dp[i][j]=(dp[i-1][j]+dp[i][j-1])%mod;
re[i][j]=(now[i-1][j]+now[i][j-1])%mod;
now[i][j]=0;
break;
}
default :
{
dp[i][j]=(dp[i-1][j]+dp[i][j-1])%mod;
re[i][j]=(re[i-1][j]+re[i][j-1])%mod;
now[i][j]=((now[i-1][j]+now[i][j-1])*10+re[i][j]*(c[i][j]-'0'))%mod;
break;
}
}
}
}
printf("%lld",(dp[a][b]+now[a][b])%mod);
return 0;
}