#212. 矩阵

来源:互联网 发布:矢量动画制作软件 编辑:程序博客网 时间:2024/06/07 00:05

输出时忘记%lld+打错模数=自爆

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<cstdlib>using namespace std;#define rep(i,j,k) for(i=j;i<=k;++i)#define per(i,j,k) for(i=j;i>=k;--i)#define ll long long#define db double#define mkp(x,y) make_pair(x,y)#define pii pair<int,int>#define X first#define Y secondconst int N=130;const ll MOD=100000000000000000LL;int n,a,b,c,S[N],SS[N];ll f[N][N][N];void add(ll &x,ll y){x+=y;if(x>=MOD)x-=MOD;}int main(){scanf("%d%d%d%d",&n,&a,&b,&c);int h,i,j,k,i1,j1,k1;f[0][0][0]=1;rep(h,1,n){scanf("%d",&S[h]);SS[h]=SS[h-1]+S[h];}if(SS[n]!=a+b+c){puts("0");return 0;}rep(h,1,n)per(i,S[h],0)per(j,S[h]-i,0)per(i1,min(a-i,SS[h-1]),0)per(j1,min(b-j,SS[h-1]-i1),0)add(f[h][i1+i][j1+j],f[h-1][i1][j1]);printf("%lld\n",f[n][a][b]);return 0;}

这个O(n^5)的代码在simpleoj上跑得飞快,直接A掉。

然后考虑优化。

使用前缀和,将所有对f[h][i][j]有贡献的f[h-1][i1][j1]搞成前缀和。这些i1、j1满足以下条件:

这张图告诉我们,用g[h][k]来存k=i+j时有贡献的f[h-1][i1][j1]的和。转移时只要加入斜斜的那一条就可以了