Codeforces Round #242 (Div. 2) C: Magic Formulas 神奇的异或算式

原题链接:Codeforces 424C - Magic Formulas(大家自行把链接头的https改成http)

题目大意:题目已经说得很清楚了,就是给定p1, p2, ..., pn,求Q



大致思路:异或操作满足交换律,所以 Q = q1^q2^.......^qn =(p1^p2......^pn) ^ [ ((1%1)^....^(1%n)) ^ ((2%1)^......^(2%n)) ^.... ^((n%1)^....^(n%n)) ] 。其中红色部分可直接在读入数据时完成,关键在于绿色部分的处理。 绿色部分其实可以转化成矩阵:

0   1%2  ...........  1%n

0   2%2  ............ 2%n

0   3%2  ............ 3%n
.....................................
0   n%2 ............. n%n

第一列全部是0,全部求异或的结果也是0。第二列开始就有规律了,每一列都以列号i作为循环周期,比如第二列为1、0、1、0、1……,周期为2;第三列为1、2、0、1、2、0、1……,周期为3。根据异或的规律,每个数字出现两次的话,异或结果即为0。所以我们只要计算每列以2*i为周期循环剩下的那几个数即最后的 n%(2*i) 个数的异或即可,具体实现如下:

#include <iostream>
#include <cstdio>
using namespace std;

int cal(int n, int order) {
    int temp = n%(order*2);
    int res = 0, j=1;
    for(int i=0; i<temp; i++) {
        res ^= j;
        j++;
        if(j==order) j=0; //实际每列以order为周期,每个周期最后一个数为0,所以需要重置一次
    }
    return res;
}

int main() {
    int n, x;
    int res = 0;
    scanf("%d%*c", &n);

    for(int i=1; i<=n; i++) {
        scanf("%d", &x);
        res ^= x;
        if(i>=2) res ^= cal(n,i);
    }
    cout<<res<<endl;
    return 0;
}
      跑一遍发现超时了,很显然cal函数不能放在循环里,该怎么改?  其实,如果再仔细观察一下就会发现每次cal函数循环部分计算的内容是递增形式的,比如有时是1^2^3,有时可能就是1^2^3^4,每次计算的必定是连续数字的异或,所以这些计算的结果可以事先计算好,这样就不用在主函数循环内再嵌套一层循环了,具体实现代码:

#include <iostream>
#include <cstdio>
using namespace std;

int m[1000005];

int main() {
    int n, x;
    int res = 0;
	m[0] = 0;
	
    scanf("%d%*c", &n);
	for(int i=1; i<=n; i++)
		m[i] = m[i-1] ^ i;

    for(int i=1; i<=n; i++) {
        scanf("%d", &x);
        res ^= x;
        if((n/i)%2==1) res ^= m[i-1];
		res ^= m[n%i];
    }
    cout<<res<<endl;
    return 0;
}

      修改后的代码中,使用数组m事先计算好后面要用到的异或结果。具体的使用在 19、20 行:先判断是否有奇数个大小为 i 的周期(偶数个异或的结果就为0了),如果有就“加上”一个周期的异或结果;然后再“加上”不满一个周期部分的异或结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值