[20200720NOIP提高组模拟T1]矩阵的个数

题目通道:

   https://www.luogu.com.cn/problem/P5784

题目大意:

 给你一个数n,表示全为非负数的矩阵大小为3*n,给你3个数$c_{1}$、$c_{2}$、$c_{3}$,分别表示矩阵第一、二、三列的数值之和,再给你n个数,表示第$a_{i}$行的数值之和,请你求出满足条件的矩阵的个数.

solution:

 一开始没什么思路,写了手dfs,直觉特判压缩第三列,复杂度O($n^{2}n!$),显然过不去.接着在dfs基础上考虑记忆搜,数组需开到250*150*150,空间较为吃力,时间也有些紧张,代码也不太好写.所以考虑直接递推dp,滚动数组滚掉一个维度,在$1--n$上考虑状态转移,特判维护第三列数值的合法.

code:

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define R register
#define next exnttttnext
#define debug puts("MLG")
#define mod 100000000000000000
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
inline ll read();
inline void write(ll x);
inline void writesp(ll x);
inline void writeln(ll x);
ll n,c1,c2,c3;
ll num[1000],sum[1000];
ll f[250][250][2];
int main(){
    n=read();c1=read();c2=read();c3=read();
    for(R ll i=1;i<=n;i++) num[i]=read(),sum[i]=sum[i-1]+num[i];
    if(sum[n]!=c1+c2+c3){
        writeln(0);
        return 0;
    }
    f[0][0][0]=1;
    for(R ll i=1;i<=n;i++){
        for(R ll j=0;j<=sum[i]&&j<=c1;j++){
            for(R ll k=0;k+j<=sum[i]&&k<=c2;k++){
                f[j][k][i&1]=0;
                if(sum[i]-j-k>c3) continue;
                for(R ll u=0;u<=num[i];u++){
                    for(R ll v=0;u+v<=num[i];v++){
                        if(j-u<0||k-v<0||(sum[i]-j-k)-(num[i]-u-v)<0) continue;
                        f[j][k][i&1]+=f[j-u][k-v][(i&1)^1];
                        f[j][k][i&1]%=mod;
                    }
                }
            }
        }
    }
    writeln(f[c1][c2][n&1]);
}
inline ll read(){
    ll x=0,t=1;char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') t=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*t;
}
inline void write(ll x){
    if(x<0){putchar('-');x=-x;}
    if(x<=9){putchar(x+'0');return;}
    write(x/10);putchar(x%10+'0');
}
inline void writesp(ll x){
    write(x);putchar(' ');
}
inline void writeln(ll x){
    write(x);putchar('\n');
}

 

posted @ 2020-07-20 14:17  月落乌啼算钱  阅读(148)  评论(0)    收藏  举报