POJ 1742 Coins

题目链接

题意

给出N个硬币和数量,求一共可以组合成几种情况

AC

  • bitset
    用二进制的下标表示和,最后1的个数表示种类数
    优化:用二次方移动加快速度
    例如:

移动7次(需要4次)
1.0000 0000 1
2.0000 0001 1 移动1,剩余6
3.0000 0111 1 移动2,剩余4
4.0111 1111 1 移动4,剩余0

移动10次(需要5次)
1.0000 0000 0000 1
2.0000 0000 0001 1 移动1,剩余9
3.0000 0000 0111 1 移动2,剩余7
4.0000 0111 1111 1 移动4,剩余3
剩余3
0011 1111 1111 1 移动3,剩余0

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <map>
#include <bitset>
#include <string.h>
#include <cmath>
#include <algorithm>
#define N 1000015
#define P pair<int,int>
#define ll long long
#define mk(a, b) make_pair(a, b)
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
bitset<100005> a;
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int n, m;
    while (cin >> n >> m, n + m) {
        a.reset();
        vector<P> v(n);
        for (int i = 0; i < n; ++i) {
            cin >> v[i].first;
        }
        for (int i = 0; i < n; ++i) {
            cin >> v[i].second;
        }
        a[0] = 1;
        // for (int i = 0; i < n; ++i) {
        //  for (int j = 1; j <= v[i].second; ++j) {
        //      a |= a << (v[i].first);
        //  }
        // }
        for (int i = 0; i < n; ++i) {
            // 每次移动2的次方,这样可以加快速度 log
            for (int j = 1; j <= v[i].second; j <<= 1) {
                v[i].second -= j;
                a |= a << (j * v[i].first);
            }
            a |= a << (v[i].second * v[i].first);
        }
        int ans = 0;
        for (int i = 1; i <= m; ++i) {
            if (a[i] == 1)  ans++;
        }
        cout << ans << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/henuyh/article/details/81089926