暴力____zxa and xor( hdu 5683 BestCoder Round #83 )

问题描述
zxa最近对按位异或(exclusive disjunction)产生了极大的兴趣,为此他拿出了一个长度为nn的非负整数序列a_1,a_2,\cdots,a_na1,a2,,an。

zxa觉得这样太单调了,于是他定义了一种方法funct(x,y)funct(x,y),表示将a_xax不可逆转地修改为yy后计算\otimes_{1\leq i < j\leq n}{(a_i+a_j)}1i<jn(ai+aj)作为该方法的返回值。

zxa很好奇,如果他对这个序列调用mm次这样的方法,那么每次得到的返回值分别是多少,你能帮助他吗?

提示:\otimes_{1\leq i < j\leq n}{(a_i+a_j)}1i<jn(ai+aj)(a_1+a_2)\otimes(a_1+a_3)\otimes\cdots\otimes(a_1+a_n)\otimes(a_2+a_3)\otimes(a_2+a_4)\otimes\cdots\otimes(a_2+a_n)\otimes\cdots\otimes(a_{n-1}+a_n)(a1+a2)(a1+a3)(a1+an)(a2+a3)(a2+a4)(a2+an)(an1+an)
输入描述
第一行有一个正整数TT,表示有TT组数据。

对于每组数据:

第一行有两个正整数nnmm。

第二行有nn个非负整数,表示a_1,a_2,\cdots,a_na1,a2,,an。

接下来mm行,第i(1\leq i\leq m)i(1im)行有两个非负整数xxyy,表示第ii调用的是funct(x,y)funct(x,y)。

每一行相邻数字之间只有一个空格。

1\leq T\leq 1000,2\leq n\leq 2\cdot10^4,1\leq m\leq 2\cdot10^4,0\leq a_i,y\leq 10^9,1\leq x\leq n,1\leq\sum{n},\sum{m}\leq10^51T1000,2n2104,1m2104,0ai,y109,1xn,1n,m105
输出描述
对于每组数据,输出mm行,第i(1\leq i\leq m)i(1im)行包含一个非负整数,表示第ii次调用方法的返回值。
输入样例
1
3 3
1 2 3
1 4
2 5
3 6
输出样例
4
6
8
Hint
第一次操作后序列为\{4,2,3\}{4,2,3}(4+2)\otimes(4+3)\otimes(2+3)=4(4+2)(4+3)(2+3)=4。

第二次操作后序列为\{4,5,3\}{4,5,3}(4+5)\otimes(4+3)\otimes(5+3)=6(4+5)(4+3)(5+3)=6。

第三次操作后序列为\{4,5,6\}{4,5,6}(4+5)\otimes(4+6)\otimes(5+6)=8(4+5)(4+6)(5+6)=8


分析:

看题目数据感觉暴力要超时。然而还好数据不是特别严。可以暴力过。但是还是需要优化。

如果每次改了之后重新全部异或铁定是要超时的。但是可以先把所有值异或后值得到。然后只对改了的部分重新异或可得。


#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include <cstdio>
#include<cmath>
using namespace std;
int a[100000];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m,ans=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }

        for(int i=1;i<n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                ans^=(a[i]+a[j]);
            }
        }
        for(int i=0;i<m;i++)
        {
            int r,l;
            scanf("%d%d",&r,&l);
            for(int k=1;k<=n;k++)
            {
                if(k!=r)
                ans^=(a[k]+a[r]),ans^=(a[k]+l);
            }
            a[r]=l;
            printf("%d\n",ans);
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值