zoukankan      html  css  js  c++  java
  • codeforces C. Magic Formulas 解题报告

    题目链接:http://codeforces.com/problemset/problem/424/C

    题目意思:给出 n 个数:p1, p2, ..., pn,定义:

    q1 = p1 ^ (1 mod 1) ^ (1 mod 2) ^ (1 mod 3) ...^(1 mod n);

    q2 = p2 ^ (2 mod 1) ^ (2 mod 2) ^ (2 mod 3) ...^(2 mod n);

    ...

    qn = p3 ^ (n mod 1) ^ (n mod 2) ^ (n mod 3) ...^(n mod n)

       Q = q1 ^ q2 ...^ qn 

       要求算出 Q

       很明显,如果直接做绝对是超时的。在这里,非常感谢 yk 师弟不厌其烦地为我解释思路,虽然最后我并没有按他的思路做......

       那么,不能直接算就需要从公式中找规律。首先要清楚的是,异或 ^ 运算满足交换律;所以可以先求出 p1 ^ p2 ^ ...^ pn,并且可以先求出第一列异或的结果,再跟第二列求出的异或结果异或...直到跟最后一列的结果异或。其次,假设 n 代表一个非零整数,有3条公式需要知道:(1)0 ^ n = n;(2)n ^ n  = 0(可以推广到异或偶数次自身),(3) n ^ n ^ n = n(可以推广到异或奇数次自身)。 这3个公式对后面的的计算进行简化。

        假设n = 5。接着请读者打竖看,即 1 mod 1, 2 mod 1, ..., 7 mod 1 地看。很明显这一列 异或之后 是等于0的!那么从第二列开始看:          第三列               第四列               第五列

    1 mod 2 = 1                     1 mod 3 = 1            1 mod 4 = 1         1 mod 5 = 1

    2 mod 2 = 0           2 mod 3 = 2            2 mod 4 = 2         2 mod 5 = 2

    3 mod 2 = 1                     3 mod 3 = 0            3 mod 4 = 3         3 mod 5 = 3

    4 mod 2 = 0                     4 mod 3 = 1      4 mod 4 = 0         4 mod 5 = 4

    5 mod 2 = 1                     5 mod 3 = 2            5 mod 4 = 1         5 mod 5 = 0

         观察这些数,可以得出每一列 mod 出来的结果都是比被 mod 数小的:第二列 mod 出来的结果都比 2 小 ; 第三列 mod 出来的结果都比 3 小;...第五列比 5 小。再观察发现,每一列 mod 出来的数是有周期性的。这时需要用到上面所说的后两条公式了。需要知道这些周期究竟是计数还是偶数,如果是偶数,相当于根本没有做过异或操作;否则异或一次。周期数的计算可以用这个公式 (n-n%i)/i 求出 。最后要处理的是最后面的那些不成周期的数究竟是什么,可以用到 n % i 来得出。(i 表示 每列中被mod的数)

         

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 using namespace std;
     5 
     6 const int maxn = 1e6;
     7 int num[maxn];
     8 
     9 int main()
    10 {
    11     int i, p, n, ans;
    12     num[0] = 0;
    13     for (i = 1; i <= maxn; i++)
    14         num[i] = num[i-1] ^ i;   // num[1] = 0^1; num[2] = 0^1^2; num[n] = 0^1^2...^n
    15     while (scanf("%d", &n) != EOF)
    16     {
    17         ans = 0;
    18         for (i = 0; i < n; i++)
    19         {
    20             scanf("%d", &p);
    21             ans ^= p;    // 先求出p1^p2^...^pn
    22         }
    23         for (i = 2; i <= n; i++)
    24         {
    25             int tmp = n - n % i;
    26             if ((tmp/i) & 1)      // tmp/i 表示有多少个周期数
    27                 ans ^= num[i-1];
    28             ans ^= num[n%i];     // 不成周期数的独立处理
    29         }
    30         printf("%d
    ", ans);
    31     }
    32     return 0;
    33 }
  • 相关阅读:
    利用Flot作基于时间段的曲线图
    Linux Apache使用CGI
    Windows node.js安装运行npm显示类似"ENOENT, stat 'C:UsersXXXXAppDataRoaming pm'错误
    JavaWeb返回Json格式数据JQuery Ajax无法解析的问题
    C++ 14 auto
    [原创] Jenkins slave agent 分布式构建
    [原创] Jenkins 邮件配置 (使用 Jenkins Email Extension Plugin)
    Linux 域名服务器配置
    证书管理
    Ubuntu 安装 Kubernetes
  • 原文地址:https://www.cnblogs.com/windysai/p/3697036.html
Copyright © 2011-2022 走看看