contesthunter CH Round #64 - MFOI杯水题欢乐赛day1 solve

时间:2021-04-22 09:40:49

http://www.contesthunter.org/contest/CH Round %2364 - MFOI杯水题欢乐赛 day1/Solve

Solve

CH Round #64 - MFOI杯水题欢乐赛 day1

题目描述

给定 n 和 X0,X1,...,Xn-1,求解 Y0,Y1,...,Yn-1,其中:

contesthunter CH Round #64 - MFOI杯水题欢乐赛day1 solve

f(x) 等于把 x 写成二进制后 1 的个数,比如说:

f(0)=0 , f(1)=1 , f(4)=1 , f(7)=3

其中 contesthunter CH Round #64 - MFOI杯水题欢乐赛day1 solve 表示二进制下的按位异或运算。

请依次输出 Y0,Y1,...,Yn-1 对 contesthunter CH Round #64 - MFOI杯水题欢乐赛day1 solve 取模的结果。

输入格式

输入第一行为一个正整数 n

输入第二行为 n 个非负整数,第 i 个数表示 Xi-1

输出格式

输出仅一行 n 个非负整数,第 i 个数表示 Yi-1 对 contesthunter CH Round #64 - MFOI杯水题欢乐赛day1 solve 取模的结果。

样例输入

3

1 1 1

样例输出

2 3 3

数据范围及约定

测试数据点 n Xi 特殊性质
1 <= 10 <= 10
2 <= 100 <= 100
3 <= 1000 <= 1000
4 = 65536 <= 109 所有 Ai 都相同
5 <= 105 <= 109 所有 Ai 都相同
6,7,8,9,10 <= 105 <= 109

分析:

方法1,

  可以先预处理W[j][0/1] 表示第j位是0/1的i的i的Xi值和,然后对于每位i,根据其二进制表示来累加答案即可。

  时间复杂度O(n log n) , 可以拿下全部测试点。

方法2.

考虑把n增加为2的幂,并令新增加的数字为0.

然后先把n == 2时转移矩阵写出来:

0 1
1 0

可以发现矩阵大概是这样的;

A A + T
A + T A

其中A的边长为2的幂,T为全1矩阵。

如果对于所有的边长为2的幂的矩阵,都能像这样分解的话,那么是不是就可以分治了?

首先,对于2 * 2 的矩阵来说,很显然是满足条件的。

假设对于2^k * 2 ^k的矩阵来说是满足条件的,那么考虑2 ^(k + 1) * 2 ^(k + 1)的矩阵,其左上角就是原来的2^k * 2 ^k的那个矩阵,设为A,显然对于所有的0 <= i < 2^k和0 <=j < 2 ^k,都有:

f((i+2k)⊕j)=f(i⊕j)+1

是不是说明其左上角的矩阵等于A + T ?

同理:右上角和右下角也是满足条件的。

于是就可以分治的去做了。

时间复杂度:O(n log n),可以拿下所有测试点。

AC代码:

代码很严谨,包括每个字符。。。orz

 #include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; #define N 100000 + 5
#define Mod 1000000007 int n, W[][]; inline int getint()
{
char ch = '\n';
for (; ch != '-' && (ch > '' || ch < ''); ch = getchar()) ;
int f = ch == '-' ? - : ;
int res = ch == '-' ? : ch - '';
for (ch = getchar(); ch >= '' && ch <= ''; ch = getchar())
res = (res << ) + (res << ) + ch - '';
return res * f;
} inline int Inc(int a, int b)
{
return a + b - (a + b >= Mod ? Mod : );
} int main()
{
//#ifndef ONLINE_JUDGE
// freopen("solve.in", "r", stdin);
// freopen("solve.out", "w", stdout);
// #endif n = getint();
int d = (int) log2(n);
for (int i = ; i < n; i ++)
{
int t = getint();
for (int j = ; j <= d; j ++)
W[j][((i >> j) & )] = Inc(W[j][((i >> j) & )], t);
}
for (int i = ; i < n; i ++)
{
int res = ;
for (int j = ; j <= d; j ++)
res = Inc(res, W[j][((i >> j) + ) & ]);
printf("%d%c", res, (i == n - ) ? '\n' : ' ');
} // #ifndef ONLINE_JUDGE
// fclose(stdin);
// fclose(stdout);
// #endif
return ;
}