AtCoder 2346 No Need

传送门:http://arc070.contest.atcoder.jp/tasks/arc070_b?lang=en

题意:

  对于一个数组的任意一个子集,如果它的元素和大于等于K这个子集就叫做good subset,如果将一个数所在的所有good subset都减去这个数,这些集合依旧是good subset那么这个数被称为无用数。现在给定一个数组,求其中的无用数的个数。 

题解:

  如果一个数不是无用数,那么所有大于等于这个数的数都不会是无用数,那么我们先对这个数组进行排序,每次二分结果就行了。

  如果当前的mid>=k,那么这个数肯定不是无用数(考虑集合中只有这一个元素的情况)。对于mid<k的这些数,我们只需将这个数去掉,查看在数组中所构成的所有集合的和是否存在属于[k-a[mid],k-1]的数。暴力求肯定会超时(O(n^3longn))。。。。

  对于上面的求和的过程我们可以通过bitset来优化,每次用sum|=sum<<a[i]来计算,最后for一遍s[sum[k-a[mis]],sum[k-1]]是否存在1就行了。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const double eps = 1e-10;
const int maxn = 5000+100;
int n,k,a[maxn];
bitset<maxn> sum;
bool judge(int x) {
    if(a[x]>=k)return 1;
    sum.reset(); sum[0]=1;
    for(int i=1;i<=n;++i) if(i!=x)sum|=sum<<a[i];
    for(int i=k-1;i>=k-a[x];--i)
        if(sum[i]) return 1;
    return 0;
}

void solve() {
    int l=0,r=n+1;
    while(l<r) {
        int mid=l+r>>1;
        if(judge(mid)) r=mid;
        else l=mid+1;
    }
    cout << l-1 << endl;
}
int main() {
#ifdef ac
    freopen("in.txt" , "r" , stdin);
//    freopen("out.txt" , "w" , stdout);
#endif
    cin >> n >> k;
    for(int i=1;i<=n;++i) cin >> a[i];
    sort(a+1, a+n+1);
    solve();
    return 0;
}

时间: 2024-10-10 22:00:20

AtCoder 2346 No Need的相关文章

AtCoder Regular Contest 075 E - Meaningful Mean 树状数组求顺序对, 前缀和

题目链接: http://arc075.contest.atcoder.jp/tasks/arc075_c 题意: 给你一个序列和一个数k,求有多少对l,r,使得a[l]+a[l+1]+...+a[r]的算术平均数大于等于k 1≤N≤2×10^5 1≤K≤10^9 1≤ai≤10^9 思路: 首先对于所有数减去k,这样就不用除(r-l+1), 然后我们发现所求的就是有多少对l,r,使得sum[r]-sum[l-1] >= 0, sum是减去k之后的序列的前缀和 用树状数组对sum求有多少个顺序对

poj 2346 Lucky tickets

题目链接:http://poj.org/problem?id=2346 思路:     使用动态规划解法: 设函数 d( n, x )代表长度为n且满足左边n/2位的和减去右边n/2位的和为x的数的数目. 将一个长度为n的数看做n个数字 A1, A2....An ( 0 <= Ai <= 9  ),将字符分为两个集合{ A1, A2....An/2 } 与 { An/2+1.....An }; 问题转换为求集合中元素和相等的数目.先从每个集合中选出一个元素,求它们差为a的可能数目,即d( 2,

Atcoder Yet Another Palindrome Partitioning(状压dp)

Atcoder Yet Another Palindrome Partitioning 思路: 一个字符串满足条件的情况是奇数字母个数小于等于1,也就是异或起来是1<<j(0<=j<=25) 记mark是异或起来的值 状态转移: dp[mark]=dp[mark]+1; dp[mark]=min(dp[mark^(1<<j)]+1,dp[mark]);(0<=j<=25) 注意dp[0]被转移后可能会变成1,但是由它转移的需要dp[0]=0,所以每次记得把d

2018.03.04 晚上Atcoder比赛

C - March Time limit : 2sec / Memory limit : 256MB Score : 300 points Problem Statement There are N people. The name of the i-th person is Si. We would like to choose three people so that the following conditions are met: The name of every chosen per

Atcoder 091/092 C 2D Plane 2N Points[扫描线]

昨晚打了第一场atcoder...这题卡了1h...今天听课的时候听到了一个极相似的题... 题意:给出2n个点的坐标(x,y) 前n个是红点,剩下是蓝点,当一个红点的横纵坐标都小于一个蓝点的时候,他们可以匹配,求最大的匹配对数 按照横坐标排序,排序后从右往左扫描,发现蓝点将其纵坐标存入set中(因为已经按照横坐标排序,所以不需要考虑横坐标),发现红点从set中找一个能跟这个点匹配的最小的点(lower_bound),注意set::lower_bound是O(logn)的,std::lower_

【赛时总结】 ◇赛时&#183;I◇ AtCoder ARC-098

◆赛时I◆ ARC-098 ■试题&解析■ ◆本场最水◆ C-Attention 长点儿信心吧-- [AtCoder ARC-098 C] [解析] 既然只存在左右(东西)两个朝向,那么领导右侧的人应朝左,相反左侧的人朝右.则要找到一个人作为领导使上述人的数量最多. 我们可以用 tot[0].tot[1] 分别储存最初朝东.西的人的个数.然后从第一个人开始枚举,统计当前人左侧的分别朝向东.西的人的个数,从而算出当前人左侧朝右.右侧朝左的人的个数,记为F.领导人即是算出F最大的人. 注意统计时要排

【赛时总结】 ◇赛时&#183;II◇ AtCoder ABC-100

◆赛时·II◆ ABC-100 ■唠叨■ ABC终于超过百场比赛啦(毫不犹豫地参加).然后莫名其妙的好像是人很多,评测慢得不可理喻.然后我就--交了一大发--错误程序--然后B题就没了.最后的D题居然是贪心(题意没看懂),我就做了个DP还wa了 (:′⌒`) ■试题&解析■ ◆泼水节◆ A-Happy Birthday! [Atcoder ABC-100 A] [翻译] E869120和square1001的16岁生日到了,来自Atcoder王国的Takahashi送给他们一个被平均切成16份的

AtCoder Grand Contest 025 Problem D

www.cnblogs.com/shaokele/ AtCoder Grand Contest 025 Problem D Time Limit: 2 Sec Memory Limit: 1024 MB Description Takahashi is doing a research on sets of points in a plane. Takahashi thinks a set \(S\) of points in a coordinate plane is a good set w

AtCoder Grand Contest 024 Problem E(动态规划)

www.cnblogs.com/shaokele/ AtCoder Grand Contest 024 Problem E Time Limit: 2 Sec Memory Limit: 1024 MB Description Find the number of the possible tuples of sequences (\(A_0,A_1,-,A_N\)) that satisfy all of the following conditions, modulo \(M\): ? Fo