AcWing 532. 货币系统

原题链接

考察:完全背包dp+线性代数

思路:

       这道题其实是求给定a数组的极大无关向量组.

       这里要能分析出一些性质:

  1. 如果(a,n)能被(b,m)所替代,那么a数组能被b数组表示
  2. b数组中gcd>1的一对数,大的没必要存在
  3. b数组是a数组的一部分元素.

     假设b数组能表示a数组,且存在一个数x属于b数组而不属于a数组.根据b数组能表示a数组,那么x能被a数组的部分元素表示.又因为这些部分元素可以被b数组的某些元素表示,所以x没有存在的必要.

     接下来就判断a数组哪些元素多余,根据常识,大数可以被小数表示,所以先排序,如果后面的元素可以被前面的元素表示,那么它可以被剔除

参考了Y总的代码,我自己写的是压线过的= =

为什么能这么写呢?因为上一轮标记的f[i][j]只会受到自己上一轮和这一轮相差a[i]的影响,而上一轮恒为1,所以不会改变

实际这题是求极大无关组元素个数的方法

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int N = 110,M = 25010;
 7 int a[N];
 8 bool f[M];
 9 int main()
10 {
11     int T;
12     scanf("%d",&T);
13     while(T--)
14     {
15         int n,maxn = 0,ans = 0;
16         scanf("%d",&n);
17         memset(f,0,sizeof f);
18         f[0] = 1;
19         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
20         sort(a+1,a+1+n);
21         for(int i=1;i<=n;i++)
22         {
23             if(!f[a[i]]) ans++;
24             for(int j=a[i];j<=a[n];j++)
25                 f[j] = f[j]|f[j-a[i]];
26         }
27         printf("%d\n",ans);
28     }
29     return 0;
30 }

 

posted @ 2021-02-02 18:38  acmloser  阅读(92)  评论(0编辑  收藏  举报