zoukankan      html  css  js  c++  java
  • 【题解】Coins(二进制拆分+bitset)

    【题解】Coins(二进制拆分+bitset)

    【vj】

    俗话说得好,bitset大法吼啊

    这道题要不是他多组数据卡死了我复杂度算出来等于九千多万的选手我还不会想这种好办法233

    考虑转移的实质是怎样的,就是对于一个(dp)数组表,平移(val_i imes num_i')位然后异或起来,这样就直接bitset开就好了。

    背包问题的转移就不说了,优化就是利用二进制来优化,方法就是,我们可以知道所有数都是二进制表示出来的,根据加法交换律以及背包转移的方法,我们从小往大枚举(2^xle num_i),然后把bitset平移(2^x)位后异或起来就好了。

    但是有个天大的问题就是怎么保证我们的方案合法,也就是说保证我们的方案中不存在硬币用得过多。

    实际上直接在循环的时候控制一下就好了,出来的方案就会(le num_i)并且每个组合都会考虑到。

    //@winlere
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<bitset>
    
    using namespace std;  typedef long long ll;
    const int maxm=1e5+5;
    const int maxn=1e2+5;
    int val[maxn],num[maxn];
    bitset < maxm > dp;
    
    int n,m;
    inline int qr(){
          register int ret=0,f=0;
          register char c=getchar();
          while(c<48||c>57)f|=c==45,c=getchar();
          while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
          return f?-ret:ret;
    }
    
    int main(){
          dp[0]=1;int ans=0;
          while(scanf("%d%d",&n,&m),n||m){
    	    for(register int t=1;t<=n;++t) val[t]=qr();
    	    for(register int t=1;t<=n;++t) num[t]=qr();
    	    dp&=1;
    	    for(register int t=1;t<=n;++t){
    		  for(register int i=1;i<=num[t];i<<=1)
    			if(1ll*i*val[t]<=m) dp|=dp<<(i*val[t]),num[t]-=i;
    			else num[t]-=i;
    		  if(1ll*num[t]*val[t]<=m) dp|=dp<<(num[t]*val[t]);
    	    }
    	    for(register int t=1;t<=m;++t)
    		  if(dp[t]) ++ans;
    	    printf("%d
    ",ans);
    	    ans=0;
          }
          return 0;
    }
    
    
  • 相关阅读:
    S03E01 蓝牙操作
    GET与POST方法
    Http请求头与响应头
    HttpClient初步
    Http
    深度为H的满k叉树
    html5-css选择器
    html5-css的使用强制优先级
    html5-样式表的使用-初步
    html5-css的引入
  • 原文地址:https://www.cnblogs.com/winlere/p/10868907.html
Copyright © 2011-2022 走看看