p1383

当时有人说:

于是去看了一眼,觉得动归很可写啊,于是写了写转移发现不太能直接转移,因为异或不一定是加还是减,滚动数组不好搞.于是算了算2^100也才六万多,完全可以开E*2^B的数组保存状态.

借用c++自带的^运算就写成了这样子

然后发现自己日常读错题:人家首先要求要从已有的数开始异或.而且至少运行一次.这样的话这个代码初状态就很智障了.

首先考虑换一下状态吧:可以枚举步数,这里当然是小于等于2*E的了,因为每个数字最多用两次,一般只用一次或者不用.

 那么就有又了一个显然的状态转移.

复杂度不小了,200*100*50000=超时.想到不需要用2n次,改成n就可以,参考上面的推论.但是还是超时啊.

但是第一重循环真的有用么?想一想状态更新的过程发现是完全不必要的.我们再改一下就可以跑的飞快了.为什么可以去掉一重循环呢?因为考虑这个动归类似于背包的迭代更新,输出的答案最多是每个数都用一次为n,再循环那么多次没有意义.

所以最后AC代码和第一次的有什么不一样呢?这道题为什么没有人写动归呢?我认为是初状态的设置问题.它从各种动归常用的粗暴的设(0,0)为初状态到自己枚举得到出状态,变得复杂了一些.

复杂度(E^2+E*2^B).

没了.

using namespace std;
int read()
{
    int This=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')
        ch=getchar();
    while(ch>='0'&&ch<='9')
    {
        This=(This<<1)+ch-'0';
        ch=getchar();
    }
    return This;
}
int i,f,t;
int m,n,end;
int tt[20],o[210];
void write(int aa)
{
    memset(tt,0,sizeof(tt));
    for(i=0;aa;i++)
    {
        tt[i]=aa%2;
        aa=aa/2;
    }
    for(i=log2(m);i>=0;i--)
    {
        cout<<tt[i];
    }
    return ;    
}
int wei(int a,int b)
{
    int sum=0;
    for(;a>0||b>0;)
    {
        if((a&1) != (b&1))
        {
            sum++;
        }
        a=a/2;b=b/2;
    }
    return sum;
}
int minn,ans,tstep,j;
int step[66666],can[66666];
int main()
{    
    //freopen("123.in","r",stdin);
    memset(step,0x3f,sizeof(step));
    cin>>m>>n;
    m=(1<<m)-1;
    end=read();
    for(i=1;i<=n;i++)
        o[i]=read();
    for(i=1;i<=n;i++)
    {
        can[o[i]]=1;
        step[o[i]]=min(step[o[i]],2);
        for(f=1;f<=n;f++)
        {            
            step[o[i]^o[f]]=1;
            can[o[i]^o[f]]=1;
        }
    }
    for(i=1;i<=n;i++)
    {
        for(f=0;f<=m;f++)
        {
            if(can[f])
            {
                can[f^o[i]]=1;
                step[f^o[i]]=min(step[f^o[i]],step[f]+1);
            }
        }
    }
    minn=100000;
    tstep=100000;
    for(i=m;i>=0;i--)
    {
        if(can[i])
        {
            if(wei(i,end)==minn&&step[i]<=tstep)
            {
                tstep=step[i];
                ans=i;
            }
            else if(wei(i,end)<minn)
            {
                tstep=step[i];
                minn=wei(i,end);
                ans=i;
            }
        }
    }
    cout<<tstep<<' ';
    write(ans);
}
View Code
原文地址:https://www.cnblogs.com/qywyt/p/10131737.html