zoukankan      html  css  js  c++  java
  • BZOJ 4004 [JLOI 2015] 装备购买 解题报告

    哎这个题 WA 了无数遍。。。果然人太弱。。。

    首先我们把这些装备按照花费从小到大排序,然后依次考虑是否能买这个装备。

    至于这样为什么是对的,好像有一个叫拟阵的东西可以证明,然而我不会。TATQAQ

    至于怎么考虑是否能买这个装备呢,我们可以动态更新线性基,具体操作:

    1. 对当前向量进行高斯消元,注意要从从高位往低位消。
    2. 如果消元完毕后当前向量变成了 $0$ 向量,那么我们就可以用之前的装备凑出当前装备,否则就不能凑出来。

    每次更新线性基需要 $O(m^2)$ 的时间,要更新 $O(n)$ 次。

    时间复杂度 $O(nm^2)$,稍微优化一下应该可以过吧。。。

      1 #include <cmath>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <iostream>
      5 #include <algorithm>
      6 using namespace std;
      7 typedef long long LL;
      8 #define N 500 + 5
      9 #define Mod 998244353
     10 
     11 int n, m, tot, ans;
     12 int Ord[N], W[N];
     13 
     14 struct Node
     15 {
     16     int num[N];
     17     Node () {memset(num, 0, sizeof(num));}
     18     inline void init()
     19     {
     20         for (int i = 1; i <= m; i ++)
     21             scanf("%d", num + i);
     22     }
     23     inline bool operator < (const Node a) const
     24     {
     25         for (int i = 1; i <= m; i ++)
     26         {
     27             if (num[i] != 0 && !a.num[i]) return 0;
     28             else if (!num[i] && a.num[i] != 0) return 1;
     29         }
     30         return 0;
     31     }
     32 }A[N], P[N];
     33 
     34 inline int power(int u, int v)
     35 {
     36     int res = 1;
     37     for (; v; v >>= 1)
     38     {
     39         if (v & 1) res = (LL) res * u % Mod;
     40         u = (LL) u * u % Mod;
     41     }
     42     return res;
     43 }
     44 
     45 inline bool cmp(int u, int v)
     46 {
     47     return W[u] < W[v];
     48 }
     49 
     50 inline bool All_zero(int id)
     51 {
     52     for (int i = 1; i <= m; i ++)
     53         if (A[id].num[i] != 0) return 0;
     54     return 1;
     55 }
     56 
     57 inline int Inc(int a, int b)
     58 {
     59     return a + b - (a + b >= Mod ? Mod : 0);
     60 }
     61 
     62 inline bool Modify(int id)
     63 {
     64     if (tot == m) return 0;
     65     if (!tot)
     66     {
     67         tot ++;
     68         for (int i = 1; i <= m; i ++)
     69             P[tot].num[i] = A[id].num[i];
     70         return 1;
     71     }
     72     for (int d = 1; d <= tot; d ++)
     73     {
     74         int i = 1;
     75         for (; i <= m; i ++)
     76             if (P[d].num[i] != 0) break ;
     77         if (!A[id].num[i]) continue ;
     78         int mul = (LL) A[id].num[i] * power(P[d].num[i], Mod - 2) % Mod;
     79         for (i = 1; i <= m; i ++)
     80             A[id].num[i] = Inc(A[id].num[i], Mod - ((LL) P[d].num[i] * mul % Mod));
     81     }
     82     bool ok = 0;
     83     for (int i = 1; !ok && i <= m; i ++)
     84         if (A[id].num[i] != 0) ok = 1;
     85     if (!ok) return 0;
     86     tot ++;
     87     for (int i = 1; i <= m; i ++)
     88         P[tot].num[i] = A[id].num[i];
     89     for (int d = tot; d > 1; d --)
     90     {
     91         if (P[d - 1] < P[d])
     92         {
     93             for (int i = 1; i <= m; i ++)
     94                 swap(P[d - 1].num[i], P[d].num[i]);
     95         }
     96         else break ;
     97     }
     98     return 1;
     99 }
    100 
    101 int main()
    102 {
    103     #ifndef ONLINE_JUDGE
    104         freopen("4004.in", "r", stdin);
    105         freopen("4004.out", "w", stdout);
    106     #endif
    107     
    108     scanf("%d%d", &n, &m);
    109     for (int i = 1; i <= n; i ++)
    110         A[i].init();
    111     for (int i = 1; i <= n; Ord[i] = i ++)
    112         scanf("%d", W + i);
    113     sort(Ord + 1, Ord + n + 1, cmp);
    114     for (int i = 1; i <= n; i ++)
    115     {
    116         int _i = Ord[i];
    117         if (All_zero(_i)) continue ;
    118         if (Modify(_i)) ans += W[_i];
    119     }
    120     if (!tot) ans = W[Ord[1]], tot = 1;
    121     printf("%d %d
    ", tot, ans);
    122     
    123     #ifndef ONLINE_JUDGE
    124         fclose(stdin);
    125         fclose(stdout);
    126     #endif
    127     return 0;
    128 }
    4004_Gromah
  • 相关阅读:
    【学习笔记】JS知识点整理
    x86汇编语言实践(3)
    【小知识点】网页的链接跳转
    数据库系统内幕阅读笔记-第一部分
    【MySQL】06-排序
    【MySQL】05-锁
    【Py】Python基础——杂七杂八的用法
    【MySQL】04-索引
    【MySQL】03-事务
    【MySQL】02-更新流程
  • 原文地址:https://www.cnblogs.com/gromah/p/4461296.html
Copyright © 2011-2022 走看看