codeforce-424C. Magic Formulas(数学)
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 p1, p2, ..., pn. Lets write down some magic formulas:
![](http://codeforces.com/predownloaded/e5/7f/e57fbbf0c16d0964970e5e17787053a093edf790.png)
![](http://codeforces.com/predownloaded/6b/b8/6bb804f17c2d69abd667c23a5dd2b0277164b8b6.png)
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.
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).
The only line of output should contain a single integer — the value of Q.
3
1 2 3
3
为公式2.
因为异或运算满足交换律和结合律,
所以公式 = p1^p2^……^pn^(1%1)^(1%2)^……(1%n)^(2%1)%(2%2)^……^(2%n)^……^(n%1)^(n%2)^……^(n%n)
=p1^p2^……^pn^(1%1)^(2%1)^……(n%1)^(1%2)^(2%2)^……^(n%2)^……^(1%n)%(2%n)^……^(n%n).
公式2=(1%1)^(1%2)^……(1%n)^(2%1)%(2%2)^……^(2%n)^……^(n%1)^(n%2)^……^(n%n)
=p1^p2^……^pn^(1%1)^(2%1)^……(n%1)^(1%2)^(2%2)^……^(n%2)^……^(1%n)%(2%n)^……^(n%n).
那么公式2再以后面模数分类结合。
可以的到模数从1-n的通项为Sk=(1%k)^(2%k)^.....(n%k).
那么k是从1-n取不同的数,然后公式2就为S1^S2.....^Sn。
关键是Sk的求解,每一个k,Sk=(1%k)^(2%k)^.....(n%k),其中(n%k)的值只能取(0-k),那没 (1,n)是连续的所以必定有周期,
由于a^a=0,a^0=a;
举个例子;假如n=9,k=4;
1 | 2 | 3 | 0 |
1 | 2 | 3 | 0 |
1 | |||
结果就是1,上边的两行a^a=0,所以只剩下1;
又如当n=25,k=7时。(1%7)、(2%7)……(25%7)的结果如下表。
1 |
2 |
3 |
4 |
5 |
6 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
0 |
1 |
2 |
3 |
4 |
|
|
|
上边的整行就是n/k;
下面剩下的就是n%k;
那么如果上面为偶数行&&(n%k)>=1的话那么最后的sk=1^...(n%k);
如果上面为偶数行&&n%k==0,那么sk=0;
如果上面为奇数行&&(n%k)==0,sk=1^...k;
如果上面为奇数行&&(n%k)>=1,那么sk=(n%k+1)^....k;
这样的话每个sk就很容易计算了。
1 #include<stdio.h> 2 #include<algorithm> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<iostream> 6 #include<queue> 7 #include<math.h> 8 typedef long long ll; 9 ll a[1000005]; 10 ll dd[1000005]; 11 ll cc[1000005]; 12 int main(void) 13 { 14 ll i,j,k,p,q; 15 ll pp=0; 16 dd[0]=0; 17 while(scanf("%I64d",&k)!=EOF) 18 { 19 cc[k+1]=0; 20 for(i=1; i<=k; i++) 21 { 22 scanf("%I64d",&a[i]); 23 pp^=a[i]; 24 dd[i]=(dd[i-1]^i); 25 } 26 for(i=k; i>=0; i--) 27 { 28 cc[i]=cc[i+1]^i; 29 } 30 /*那么如果上面为偶数行&&(n%k)>=1的话那么最后的sk=1^...(n%k); 31 32 如果上面为偶数行&&n%k==0,那么sk=0; 33 如果上面为奇数行&&(n%k)==0,sk=1^...k; 34 35 如果上面为奇数行&&(n%k)>=1,那么sk=(n%k+1)^....k;*/ 36 for(i=1; i<=k; i++) 37 { 38 p=k/i; 39 q=k%i; 40 if(p%2==1) 41 { 42 pp^=(cc[i]^cc[q+1]); 43 } 44 else if(p%2==0) 45 { 46 pp^=dd[q]; 47 } 48 } 49 printf("%I64d\n",pp); 50 } 51 return 0; 52 }