Codeforces 242(DIV 2) C题

C. Magic Formulas
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

People in the Tomskaya region like magic formulas very much. You can see some of them below.

Imagine you are given a sequence of positive integer numbers p1p2, ..., pn. Lets write down some magic formulas:

Here, "mod" means the operation of taking the residue after dividing.

The expression  means applying the bitwise xor (excluding "OR") operation to integers x and y. The given operation exists in all modern programming languages. For example, in languages C++ and Java it is represented by "^", in Pascal — by "xor".

People in the Tomskaya region like magic formulas very much, but they don't like to calculate them! Therefore you are given the sequence p, calculate the value of Q.

Input

The first line of the input contains the only integer n (1 ≤ n ≤ 106). The next line contains n integers: p1, p2, ..., pn (0 ≤ pi ≤ 2·109).

Output

The only line of output should contain a single integer — the value of Q.

Sample test(s)
input
3
1 2 3
output 
3
 
思路:对于本题,只需要知道公式中每个数异或了多少次,一个数与0异或还是它本身,因此同一个数异或奇数此等一一次,偶数次等于0次,比如a^a = 0,a^a^a = a,关键是怎么计算某个数被异或的次数?对于任意x,首先考虑x mod y,(y > x),结果都是x,这样的y有(n-x)个,其次余数x还有其他来源,它们是比x大且对比x大的数取模,y mod z (y > x,z > x),只有这两种来源,第一种来源容易得到,第二种就需要动脑筋了,不然暴力算的话就会超时,想想,对于第二种 :y必然有这样的形式:y = z*n + x,(n属于正整数,而且z >= i+1),只有这样的y才符合要求,等价于:y-x = z*n,到这里,我们可以从1到n枚举,这样一算n不会太大,而且第二层for循环执行的次数减少的很快,只需要每次加上((y-x)/i-(y-x)/(i+1))*i,就能得出次数,最后看是奇数还是偶数即可。里面有很多小细节,写的时候就会发现,还要注意边界问题,讨论 t = (y-x)/(i+1) 等于1的情况。
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
    int n, ans, tmp;
    while(~scanf("%d", &n)){
        ans = 0;
        for(int i = 0; i < n;i ++){
            scanf("%d", &tmp);
            ans ^= tmp;
        }
        for(int i = 1;i < n;i ++){
            int cnt = n-i;
            int t = (n-i)/(i+1);
            if(t == 1) cnt += (n-2*i);
            else if(t > 1)cnt += t*((n-i)/t-i);
            for(int j = 1;j <= t-1;j ++){
                cnt += j*((n-i)/j-(n-i)/(j+1));
            }
            if(cnt&1) ans ^= i;
        }
        printf("%d\n", ans);
    }
}


 
posted on 2014-04-30 18:39  wangzhili  阅读(138)  评论(0编辑  收藏  举报