列表

详情


NC201767. 回到过去

描述

想回到过去,试着让故事继续~
小y一直幻想着回到过去,改变历史。
终于,上帝给了他一次改变历史的机会。具体地说,他获得了n个时光胶囊。第i个时光胶囊可以让时光倒流a_i天。我们将时光倒流天数相同的时光胶囊视为同一种。
小y想恰好回到m天前。而携带过多种类的时光胶囊会浪费太多体力。所以他想知道有哪些种类的时光胶囊是必须携带的。
数据保证一定可以选择若干个胶囊能过恰好回到m天前。
详细解释请参照样例。

输入描述

第一行包含两个正整数n,m。含义见【题目描述】
第二行共n个用空格隔开的正整数,第i个整数a_i表示一个可以使时光倒流a_i天的时光胶囊。

输出描述

输出共两行。
第一行一个整数表示必须携带的时光胶囊的种类数。
第二行若干个整数。分别表示这些必须携带的时光胶囊所能时光倒流的天数。并且按照天数从小到大排序输出。

示例1

输入:

4 15
1 1 2 13

输出:

1
13

说明:

共有两种满足条件的选择方案:
方案一:1 + 1 + 13 = 15
方案二:2 + 13 = 15
两种方案中都含有13,所以13是必须被选择的一种时光胶囊。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 871ms, 内存消耗: 5356K, 提交时间: 2020-04-05 18:16:28

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,M=455;
int n,m,tot,a[N],b[N],c[N];
bitset<N>pre[M],bk[M];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++)
        if(a[i]!=a[i-1]) b[++tot]=a[i],c[tot]=1;
        else c[tot]++;
    pre[0][0]=bk[tot+1][0]=1;
    for(int i=1;i<=tot;i++)
    {
        pre[i]|=pre[i-1];
        for(int j=1;j<=c[i];j++)
            pre[i]|=pre[i]<<b[i];
    }
    for(int i=tot;i>=1;i--)
    {
        bk[i]|=bk[i+1];
        for(int j=1;j<=c[i];j++)
            bk[i]|=bk[i]<<b[i];
    }
    vector<int>v;
    for(int i=1;i<=tot;i++)
    {
        bool flag=false;
        for(int j=0;j<=m;j++)
            if(pre[i-1][j]&&bk[i+1][m-j])
            {
                flag=true;break;
            }
        if(!flag) v.push_back(b[i]);
    }
    printf("%d\n",v.size());
    for(int x:v) printf("%d ",x);
}

C++ 解法, 执行用时: 255ms, 内存消耗: 2844K, 提交时间: 2021-06-25 17:16:14

#include <stack>
#include <queue>
#include <vector>
#include <cstdio>
#include <map>
#include <bitset>
#include <cstring>
#include <iostream>
#include <bitset>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define ull unsigned long long
int n,m,a[100005],f[100005],len,ans[100005];
bitset<100005>dp[100005];
bool run(int x){
	dp[x][0]=1;
	for(int i=1;i<=n;i++){
		if(a[i]==x)continue;
		dp[x]|=(dp[x]<<a[i]);
		if(dp[x][m])return 0;
	}
	return 1;
}
int main() {
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>a[i],f[a[i]]++;
	for(int i=1;i<=100000;i++)
		if(f[i]&&run(i))ans[++len]=i;
	cout<<len<<endl;
	for(int i=1;i<=len;i++)cout<<ans[i]<<" ";
    return 0;
}

上一题