1. 程式人生 > >[USACO2.1]海明碼 Hamming Codes

[USACO2.1]海明碼 Hamming Codes

連結

洛谷
USACO


大意

求一個長度為 n n 的且後面的數與前面的數的亦或值中1的個數必須要不小於 d d 序列,如果有多組解輸出最小的那個

資料範圍: n

64 , 2 8 ,
d 7 n\leq 64,每個數\leq 2^8,d\leq 7


思路

其實大意是理解過後改變的,我們發現理解題目後這就變成了一道位運算的 s b

sb 題,用 l o w b i t lowbit 操作或者暴力都可以


程式碼

/*
ID:hzbismy1
LANG:C++
TASK:hamming
*/
#define file(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout)
#include<cstdio>
#include<cctype>
using namespace std;int n,m,d,ans[65],len,i;
bool ok;
inline char Getchar()
{
    static char buf[100000],*p1=buf+100000,*pend=buf+100000;
    if(p1==pend)
	{
        p1=buf; pend=buf+fread(buf,1,100000,stdin);
        if (pend==p1) return -1;
    }
    return *p1++;
}
inline int read()
{
	char c;int d=1,f=0;
	while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
	while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
	return d*f;
}
inline void write(register long long x)
{
	if(x<0)write(45),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+48);
	return;
}
inline int getk(register int x)
{
	int ans=0;
	while((x&-x)!=0)
	{
		ans++;
		x-=x&-x;
	}
	return ans;
}
signed main()
{
	file(hamming);
	n=read();m=read();d=read();//其實m就是限制序列中每個數的大小,不過資料很水保證有解,所以我忽略了
	ans[++len]=0;//初始化
	for(;len<n;i++)//這裡條件其實還要加上i<(1<<m),但資料水所以不需要
	{
		ok=true;
		for(register int j=1;j<=len;j++) if(getk(ans[j]^i)<d) {ok=false;break;}//判斷i是否滿足條件
		if(ok) ans[++len]=i;//滿足條件放入i
	}
	putchar(48);for(register int i=2;i<=len;i++) {if(i%10!=1) putchar(32);write(ans[i]);if(i%10==0)putchar(10);}
	if(len%10)putchar(10);//USACO噁心的卡格式
}