• 牛客练习赛41 最小相似度 解题报告


    最小相似度

    思路不错的题目

    考虑到总体的状态数只有(2^m)中,如果我们把某个串改变1位,这个改变后的串和这个串的答案就是(m-1),由此可见,每个串到另一个串都有一个距离,我们把这个距离设为改变的位数,所有串到某个串都有一个最小位数(x),这个最小位数的最大值(y)的答案(m-y)就是我们的答案。

    我们发现这就是一个最短路,直接拿bfs实现,复杂度(O(n+m2^m))

    然后还有一种(FWT)的做法

    注意到(A xor B=CRightarrow B=A xor C)

    然后我们枚举或者二分答案为(x)(C)就是确定的了,就是(C_i=[f(i)<=x]),(f(i))表示二进制串下(1)的个数

    然后(A)(C),如果存在(B_i=n)就说明所以的串都卷上去了,这个答案就合法


    Code:(BFS):

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    template <class T>
    void read(T &x)
    {
        x=0;char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) x=x*10+c-'0',c=getchar();
    }
    const int N=1<<20;
    int q[N+10],dp[N],l=1,r;
    int n,m;
    char s[23];
    int main()
    {
        memset(dp,-1,sizeof dp);
        read(n),read(m);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            int sta=0;
            for(int j=1;j<=m;j++)
                sta|=(s[j]=='1')<<j-1;
            dp[sta]=0;
        }
        for(int i=0;i<1<<m;i++)
            if(~dp[i])
                q[++r]=i;
        int ans=0;
        while(l<=r)
        {
            int now=q[l++];
            ans=ans>dp[now]?ans:dp[now];
            for(int i=0;i<m;i++)
            {
                int v=now^(1<<i);
                if(dp[v]==-1)
                    dp[q[++r]=v]=dp[now]+1;
            }
        }
        printf("%d
    ",m-ans);
        return 0;
    }
    

    Code(FWT):

    #include <cstdio>
    #include <cctype>
    template <class T>
    void read(T &x)
    {
        x=0;char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) x=x*10+c-'0',c=getchar();
    }
    const int mod=998244353,inv=499122177;
    inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
    #define mul(a,b) (1ll*(a)*(b)%mod)
    const int N=1<<20;
    int n,m,A[N],B[N],d[N];
    char s[23];
    void FWT(int *a,int len,int typ)
    {
    	for(int le=1;le<len;le<<=1)
    		for(int p=0;p<len;p+=le<<1)
    			for(int i=p;i<p+le;i++)
    			{
    				int x=a[i],y=a[i+le];
    				a[i]=add(x,y),a[i+le]=add(x,mod-y);
    				if(!typ) a[i]=mul(a[i],inv),a[i+le]=mul(a[i+le],inv);
    			}
    }
    bool check(int x)
    {
    	for(int i=0;i<1<<m;i++) B[i]=d[i]<=x;
    	FWT(B,1<<m,1);
    	for(int i=0;i<1<<m;i++) B[i]=mul(A[i],B[i]);
    	FWT(B,1<<m,0);
    	for(int i=0;i<1<<m;i++)
    		if(B[i]==n)
    			return true;
    	return false;
    }
    int main()
    {
    	read(n),read(m);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%s",s+1);
    		int sta=0;
    		for(int j=1;j<=m;j++)
    			sta|=(s[j]=='1')<<j-1;
    		++A[sta];
    	}
    	FWT(A,1<<m,1);
    	for(int i=1;i<1<<m;i++) d[i]=d[i>>1]+(i&1);
    	int l=0,r=m;
    	while(l<r)
    	{
    		int mid=l+r>>1;
    		if(check(mid)) r=mid;
    		else l=mid+1;
    	}
    	printf("%d
    ",l);
    	return 0;
    }
    

    2019.3.2

  • 相关阅读:
    Android自定义之ScrollView下拉刷新
    android Viewpager取消预加载及Fragment方法的学习
    Android上下左右滑动,显示底层布局
    android权限大全
    android学习之VelocityTracker
    Android之自定义(上方标题随ViewPager手势慢慢滑动)
    Red Hat Enterprise Linux 7.5安装极点五笔
    Red Hat Enterprise Linux 7.5安装盘内容做本地YUM源
    RHEL7+Oracle11g笔记
    CentOS安装VNC方法
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10459737.html
Copyright © 2020-2023  润新知