【JZOJ4901】【NOIP2016提高A组集训第18场11.17】矩阵 题目描述 数据范围 =w= 代码 =o=
他是一名普通的农电工,他以一颗无私奉献的爱岗敬业之心,刻苦钻研业务,以娴熟的技术、热情周到的服务赢得了广大客户的尊敬和赞美。他就是老百姓称为“李电”的李春来。
众所周知,李电很喜欢YY。一天,他又YY 了奇怪的东西。他假设他自己成了神,然后他说:“出来吧,矩阵。”然后一个N _M 的矩阵从天而降。他为了不要让矩阵太大而使得自己眼花缭乱,所以他将M 固定在了3。但是,一天之后,他想继续他之前的YY,继续玩他的矩阵,但是他的记忆力太差了,所以他不记得他原来的矩阵长得什么样,所幸的是他昨天记录下了矩阵中每行每列的和,还有矩阵的每项都是非负整数。所以他想知道满足这样条件的矩阵总共有多少种。
数据范围
对于20% 的数据,满足n <= 3,0<=a,b,c,s_i<=10
对于40% 的数据,满足n<=10,0<=a,b,c,s_i<=20
对于60% 的数据,满足n<=40,0<=a,b,c,s_i<=40
对于100% 的数据,满足n<=125,0<=a,b,c,s_i<=125
=w=
设f[i][j][k]表示,第i行中第一列填个j,第二列中填个k。
。
然后咧,这个是的。
考虑一个第i行:
根据转移方程,f[i][j][k]是由图中这个黑色的等腰直角三角形转移过来的。
那么考虑维护这个等腰直角三角形:
黑色等腰直角三角形=红色长方形-(黄色等腰直角三角形-青绿色等腰直角三角形)
显然矩形前缀和以及腰所在的直线在x轴的等腰直角三角形前缀和容易维护。
时间复杂度为。
代码
Const
maxn=135;
mo=100000000000000000;
Var
n,i,j,k,l,o:longint;
m1,m2,m3:longint;
f:array[0..maxn,0..maxn,0..maxn] of int64;
a,sum:array[0..maxn] of longint;
Function max(a,b:longint):longint;
begin
if (a>b) then exit(a);
exit(b);
end;
Begin
assign(input,'mat.in');reset(input);
assign(output,'mat.out');rewrite(output);
readlN(n);
readlN(m1,m2,m3);
for i:=1 to n do
begin
read(a[i]);
sum[i]:=sum[i-1]+a[i];
end;
if (sum[n]>m1+m2+m3) or (sum[n]<m1+m2+m3) then
begin
writeln(0);
end
else
begin
f[0][0][0]:=1;
for i:=1 to n do
begin
for j:=0 to m1 do
for k:=0 to m2 do
begin
if (sum[i]<j+k) then break;
if (sum[i]-j-k>m3) then continue;
for l:=0 to j do
for o:=max(0,j+k-a[i]-l) to k do
begin
if (sum[i]-j-k>=sum[i-1]-l-o) then
begin
f[i][j][k]:=(f[i][j][k]+f[i-1][l][o]) mod mo;
end;
end;
end;
end;
writeln(f[n][m1][m2]);
end;
close(input);close(output);
End.
=o=
当一个f[i]从f[i-1]转移过来时,可以画个平面直角坐标系,看看要维护的是什么。
有必要的话,建立空间直角坐标系。