• NOIP2018货币系统


    题目大意

    给出一组数,求出其中共有多少数不能被其他数表示

    解题思路

    法一:可爱的动态规划

    这个思路还是比较好想的(也比较好写?)

    有依赖关系的背包,思路这道题是差不多的 填满型01背包

    (关于代码) 写起来坑还是比较多的,ans,f记得清零,边界记得写就不说了,转移方程那里

    f[j] |= f[j - a[i]];  

    或符号是一定要加的,举个栗子说明:

    以样例为例

    a[i] = 3,更新f[3],f[6],f[9],f[12]等等,如果不写或符号,  在a[i]=10更新时会出现 f[12] = f[2] = 0的情况

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 25050;
    #define fr(i,n) for(register int i = 1; i <= n; i++)
    int n,t,m,ans,maxn,a[N],f[N];
    
    int main()
    {
      scanf("%d",&t);
      while(t--){
          scanf("%d",&n);
          fr(i,n) scanf("%d",a + i);
        sort(a + 1, a + 1 + n);
          ans = 0;
          memset(f,0,sizeof(f));  f[0]=1;
          fr(i,n){
              if(f[a[i]]) continue;
              ans++;
              f[a[i]] = 1;
              for(int j = a[i]; j <= a[n]; j++)  
              f[j] |= f[j - a[i]];        }
        printf("%d
    ",ans);
      }
      return 0; 
    }
     法二:

    某种筛(原谅数论全忘光的蒟蒻不知道这是哪种)

    实际上和背包思路差不多的……然鹅因为是成倍成倍的筛的所以可能快点?emmm

    下面是luogu题解大佬 txtxj 的代码(对我真的懒得打)

    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int mon[25001]={};
    /*
    mon[i]=0 表示i面值的钱不能被凑出来
    mon[i]=1 表示i面值的钱可以被凑出来
    mon[i]=2 表示i面值的钱是货币系统中本来就有的钱
    */
    int coins[101]={};//存钱的面值
    int T,n,ans=0;
    int main()
    {
        scanf("%d ",&T);
        while (T--)
        {
            ans=0;
            memset(mon,0,sizeof(mon));
            memset(coins,0,sizeof(coins));
            scanf("%d",&n);
            for (int i=1;i<=n;i++)
            {
                scanf("%d",&coins[i]);
                mon[coins[i]]=2;
            }
            //把货币系统中的钱标好
            sort(coins+1,coins+1+n);
            for (int i=1;i<=coins[n];i++)
            {
                if (mon[i]>0)
                //如果mon[i]能被凑出来
                //那么mon[i+coins[j]]也能被凑出来
                {
                    for (int j=1;j<=n;j++)
                        if (i+coins[j]<=coins[n])
                        //防止数组越界
                            mon[i+coins[j]]=1;
                        else break; 
                }
            }
            for (int i=1;i<=coins[n];i++)
                if (mon[i]==2) ans++;
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    f2fs源码解析(五) node管理结构梳理
    没有什么好神秘的: wait_on_page_bit
    write_back 浅浅分析
    f2fs解析(六)
    转载软件需求文档标准格式
    转载 如何设计一个优秀的数据库
    转载 MySQL创建表的语句 示例
    equals和==的区别 (Java基础)
    转载 【Linux】Linux中常用操作命令
    windows 注册表
  • 原文地址:https://www.cnblogs.com/phemiku/p/11759235.html
Copyright © 2020-2023  润新知