hdu6129 Just do it

链接

http://acm.hdu.edu.cn/showproblem.php?pid=6129

题解

考虑第一个数对后面的影响,我用 a k a^k ak表示 a a a自身异或 k k k
a , b , c a,b,c a,b,c
a , a b , a b c a, ab, abc a,ab,abc
a , a 2 b , a 3 b 2 c a,a^2b,a^3b^2c a,a2b,a3b2c
a , a 3 b , a 6 b 2 c a,a^3b,a^6b^2c a,a3b,a6b2c
a , a 4 b , a 10 b 3 , c a,a^4b,a^{10}b^3,c a,a4b,a10b3,c
然后把 a a a的异或次数的矩阵写出来
1 0 0
1 1 1
1 2 3
1 3 6
1 4 10

其实还可以写的更宽一些(去掉第一行)
1 1 1 1 1
1 2 3 4 5
1 3 6 10 15

我自己也做到这里了,但是我就是看不出规律,我横着看竖着看,做差也看不出规律

结果上网一查题解,啥?还能斜着看?
斜着看就是杨辉三角?

算我输了

斜着看确实是杨辉三角

如果给行和列都从 0 0 0开始编号,就得到第 i i i行的第 j j j个数是 C i + j j C_{i+j}^j Ci+jj
那么最后一行的第 i i i个数就是 C m − 1 i i C_{m-1_i}^i Cm1ii

我只确定每个数字的奇偶性,就可以知道它对后面有没有贡献,这个可以直接数阶乘里的 2 2 2的个数
如果一个这个系数是奇数,那就把这个地方设为 1 1 1,否则设为 0 0 0

然后后面的数的系数就是第一个系数的平移,我现在要算出最后每个数值

然后就不会了,感觉这东西类似多项式卷积的计算,确要让你异或

看了看题解,竟然都是暴力?

貌似是因为大多数系数都等于 0 0 0只有少数等于 1 1 1

太神了这题

代码

#include 
#define maxn 200010
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-48;
    return f*x;
}
ll n, a[maxn], m;
ll count2(ll x)
{
    ll ans(0);
    while(x)
    {
        ans+=x>>1;
        x>>=1;
    }
    return ans;
}
ll calc(ll n, ll m)
{
    ll ans=count2(n)-count2(m)-count2(n-m);
    return ans;
}
ll ans[maxn], c[maxn];
int main()
{
    ll i, j, T=read();
    while(T--)
    {
        n=read(), m=read();
        for(i=0;i<n;i++)a[i]=read();
        cl(ans);
        for(i=0;i<n;i++)
        {
            auto t=calc(m+i-1,i);
            if(t==0)
            {
                for(j=i;j<n;j++)
                {
                    ans[j]^=a[j-i];
                }
            }
        }
        for(i=0;i<n;i++)
        {
            printf("%lld",ans[i]);
            if(i<n-1)putchar(32);
        }
        putchar(10);
    }
    return 0;
}

你可能感兴趣的:(特殊技巧)