zoukankan      html  css  js  c++  java
  • 【JZOJ4901】【NOIP2016提高A组集训第18场11.17】矩阵

    题目描述

    他是一名普通的农电工,他以一颗无私奉献的爱岗敬业之心,刻苦钻研业务,以娴熟的技术、热情周到的服务赢得了广大客户的尊敬和赞美。他就是老百姓称为“李电”的李春来。
    众所周知,李电很喜欢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。
    f[i][j][k]=f[i1][ja][kb]并且满足a+b<=s[i]
    然后咧,这个是O(n5)的。
    考虑一个第i行:
    这里写图片描述
    根据转移方程,f[i][j][k]是由图中这个黑色的等腰直角三角形转移过来的。
    那么考虑维护这个等腰直角三角形:
    黑色等腰直角三角形=红色长方形-(黄色等腰直角三角形-青绿色等腰直角三角形)
    显然矩形前缀和以及腰所在的直线在x轴的等腰直角三角形前缀和容易维护。


    时间复杂度为O(n3)

    代码

    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]转移过来时,可以画个平面直角坐标系,看看要维护的是什么。
    有必要的话,建立空间直角坐标系。

  • 相关阅读:
    高性能分布式计算与存储系统设计概要
    .NET核心代码保护策略
    Web 通信 之 长连接、长轮询(long polling)
    C++数据结构之二叉查找树(BST)
    T4:T4 笔记 + Trait 示例
    腾讯2014软件开发
    CSS选择器从右向左的匹配规则
    Js面向对象编程
    Js杂谈-正则的测试与回溯次数
    Microsoft Message Analyzer (微软消息分析器,“网络抓包工具
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714824.html
Copyright © 2011-2022 走看看