FZU Code Carnival -Winner Winner(赢家,赢家)(位运算与状态压缩)

The FZU Code Carnival is a programming competetion hosted by the ACM-ICPC Training Center of Fuzhou University. The activity mainly includes the programming contest like ACM-ICPC and strive to provide participants with interesting code challenges in the future.

FZU代码狂欢节是一个由福州大学AMC-ICPC训练中心举办的程序设计竞赛。这个活动主要包含像ICPC这样的程序竞赛,并且以后尽力为参赛者提供有趣的代码挑战。
Before the competition begins, YellowStar wants to know which teams are likely to be winners. YellowStar counted the skills of each team, including data structure, dynamic programming, graph theory, etc. In order to simplify the forecasting model, YellowStar only lists M skills and the skills mastered by each team are represented by a 01 sequence of length M. 1 means that the team has mastered this skill, and 0 does not.

在比赛开始前,黄星想去知道哪一队更可能是赢家。黄星计算了一下每一个队的能力值,包含数据结构,动态规划,图论等方面。为了简化预测模型,黄星只列出M种技巧,以及被每个队掌握的技巧,这由一个长度为M的01序列组成。1代表这个队伍掌握了这个知识点,0则没有。
If a team is weaker than other teams, this team cannot be a winner. Otherwise, YellowStar thinks the team may win. Team A(a1, a2, ..., aM ) is weaker than team B(b1, b2, ..., bM ) if ∀i ∈ [1, M], ai ≤ bi and ∃i ∈ [1, M], ai < bi.
Since YellowStar is busy preparing for the FZU Code Carnival recently, he dosen’t have time to forecast which team will be the winner in the N teams. So he asks you to write a program to calculate the number of teams that might be winners.

如果一个队伍比其他队伍若,这个队伍就没法获胜。否则,黄星就会认为这个队伍可以胜利。Team A比Team B 弱的条件是:全体ai小于等于bi且存在一个i值使得bi>ai。

输入 

Input is given from Standard Input in the following format:

输入以下列形式给出.
N M
s1 s2 . . . sN
The binary representation of si indicates the skills mastered by teami.

si的二进制形式表示各个队伍掌握的技能情况。
Constraints
1 ≤ N ≤ 2 × 106
1 ≤ M ≤ 20
0 ≤ si < 2M

输出

Print one line denotes the answer.

输出一行,代表最终答案

输入

3 3
2 5 6

输出

2

由于题目中给的信息是几个常数,然后用几个常数展开的01序列计算,所以也代表我们可以从二进制的方法得到些什么启示。

我们知道,01序列中每乘一个2就会使得整个数(所有的1)同时向左移动一个位,同理,每除一个2就同时向右移动一个位。那我们可以用1(00001)这个数字通过左右移来实现“掌握某一项技巧(即某一位是1)”的效果。

考虑如下细节

  1. 假如一个队伍的能力序列为10101,那么它肯定要比10100或者00101或者10001要强,但是和11100这样1的数量相等的队伍实力相当。
  2. 给定的si最大值为\large 2^m
  3. 01背包问题里,我们总是可以通过拿与不拿一个物品来确定当前的状态,而在这里恰好是0与1的关系(会与不会),两者比较吻合。

所以我们可以使用一个“类动态规划算法”。由于所给数据从数值上并不连续,那么通过枚举\large 2^m~0中存在的值(十进制表示的01序列),并且利用类似01背包的思想(拿与不拿)对他们进行处理即可。

所以有如下思路:

  1. 确定给定的十进制数字中的最大值,尽可能缩小枚举范围。
  2. 从确定的最大值枚举到0,遍历每一种题目数据中存在的01组合。之后以1<<j(j∈[0,m-1])的形式遍历部分事件空间并否定这一技巧不会(当前这个1是0)但是其他情况与当前队伍相同的01序列(比如10101与00101就1位不同,可以通过这个否定00101)
  3. 计算未被否定的数字个数。

有代码如下 :

#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <algorithm>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf("%lld",&a)
#define din(a) scanf("%d",&a)
#define printlnlld(a) printf("%lld\n",a)
#define printlnd(a) printf("%d\n",a)
#define printlld(a) printf("%lld",a)
#define printd(a) printf("%d",a)
#define reset(a,b) memset(a,b,sizeof(a))
const long long int INF=0x3f3f3f3f;
using namespace std;
const double PI=acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod=1000000007;
const int tool_const=1999112620000907;
const int tool_const2=33;
inline ll Unnamed_Scanner()
{
    ll tmp=0,si=1;
    char c=getchar();
    while(c>'9'||c<'0')
    {
        if(c=='-')
            si=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        tmp=tmp*10+c-'0';
        c=getchar();
    }
    return si*tmp;
}
///Schlacht von Stalingrad
/**Although there will be many obstructs ahead,
the desire for victory still fills you with determination..**/
ll dp[5004352];
int DETERMINATION()
{
    ll n,m;
    cin>>n>>m;
    ll tmp;
    ll mx=-1;
    for(int i=1;i<=n;i++)
    {
        cin>>tmp;
        dp[tmp]++;
        mx=max(mx,tmp);//找出最大值
    }
    ll ans=0;
    for(int i=mx;i>=0;i--)
    {
        if(dp[i])//存在这样的十进制数据
        {
            if(dp[i]>0)//未被否定
            ans+=dp[i];//统计一下
            for(int j=m-1;j>=0;j--)
                if(i&(1<<j))//如果i的从右往左数的第j+1位是1(掌握了技巧)
                  dp[i^(1<<j)]=-1;//把这一位是0而且其他情况与当前相同的01序列否定。
        }
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43874261/article/details/89932071