【51Nod1773】A国的贸易 FWT+快速幂
2017-12-29 09:32
274 查看
题目描述
给出一个长度为 $2^n$ 的序列,编号从0开始。每次操作后,如果 $i$ 与 $j$ 的二进制表示只差一位则第 $i$ 个数会加上操作前的第 $j$ 个数。求 $t$ 次操作后序列中的每个数是多少。
输入
第一行两个正整数 n , t,意义如题。
第二行 2^n 个非负整数,第 i 个数表示编号为 i-1 的城市的初始货物存储量。
n<=20 t<=10^9
输出
输出一行 2^n 个非负整数。
第 i 个数表示过了 t 天后,编号为 i-1 的城市上的货物数量对 1e9+7 取模的结果。
样例输入
3 2
1 2 3 4 5 6 7 8
样例输出
58 62 66 70 74 78 82 86
题解
FWT+快速幂
显然构建 $b$ 数组,其中 $b[0]=1$ ,$b[2^i]=1$ ,其余为 $0$ ,那么原序列 $a$ 经过一次操作后得到的新序列就是 $a\oplus b$ ,其中 $\oplus$ 表示两个数组的异或卷积。
于是就好办了,先求出 $a[]$ 和 $b[]$ 的FWT,然后直接按位计算 $c[i]=a[i]*b[i]^t$ ,再求逆fwt即可。
时间复杂度 $O(2^n·n)$
注意本题卡常,因此必须加读入优化和输出优化。
给出一个长度为 $2^n$ 的序列,编号从0开始。每次操作后,如果 $i$ 与 $j$ 的二进制表示只差一位则第 $i$ 个数会加上操作前的第 $j$ 个数。求 $t$ 次操作后序列中的每个数是多少。
输入
第一行两个正整数 n , t,意义如题。
第二行 2^n 个非负整数,第 i 个数表示编号为 i-1 的城市的初始货物存储量。
n<=20 t<=10^9
输出
输出一行 2^n 个非负整数。
第 i 个数表示过了 t 天后,编号为 i-1 的城市上的货物数量对 1e9+7 取模的结果。
样例输入
3 2
1 2 3 4 5 6 7 8
样例输出
58 62 66 70 74 78 82 86
题解
FWT+快速幂
显然构建 $b$ 数组,其中 $b[0]=1$ ,$b[2^i]=1$ ,其余为 $0$ ,那么原序列 $a$ 经过一次操作后得到的新序列就是 $a\oplus b$ ,其中 $\oplus$ 表示两个数组的异或卷积。
于是就好办了,先求出 $a[]$ 和 $b[]$ 的FWT,然后直接按位计算 $c[i]=a[i]*b[i]^t$ ,再求逆fwt即可。
时间复杂度 $O(2^n·n)$
注意本题卡常,因此必须加读入优化和输出优化。
#include <cstdio> #include <cctype> #define N 1050000 #define mod 1000000007 typedef long long ll; ll a , b ; inline char nc() { static char buf[100000] , *p1 , *p2; return p1 == p2 && (p2 = (p1 = buf) + fread(buf , 1 , 100000 , stdin) , p1 == p2) ? EOF : *p1 ++ ; } inline int read() { int ret = 0; char ch = nc(); while(!isdigit(ch)) ch = nc(); while(isdigit(ch)) ret = ((ret + (ret << 2)) << 1) + (ch ^ '0') , ch = nc(); return ret; } char pbuf[15000000] , *pp = pbuf; inline void write(ll x) { static int sta[12]; int top = 0; if(!x) *pp ++ = '0'; while(x) sta[top ++ ] = x % 10 , x /= 10; while(top -- ) *pp ++ = sta[top] ^ '0'; *pp ++ = ' '; } ll pow(ll x , int y) { ll ans = 1; while(y) { if(y & 1) ans = ans * x % mod; x = x * x % mod , y >>= 1; } return ans; } void fwt(ll *a , int n , int flag) { int i , j , k , t; for(i = 1 ; i < n ; i <<= 1) for(j = 0 ; j < n ; j += (i << 1)) for(k = j ; k < j + i ; k ++ ) t = a[k] , a[k] = (t + a[k + i]) * flag % mod , a[k + i] = (t - a[k + i] + mod) * flag % mod; } int main() { int n = 1 << read() , m = read() , i; for(i = 0 ; i < n ; i ++ ) a[i] = read(); b[0] = 1; for(i = 1 ; i < n ; i <<= 1) b[i] = 1; fwt(a , n , 1) , fwt(b , n , 1); for(i = 0 ; i < n ; i ++ ) a[i] = a[i] * pow(b[i] , m) % mod; fwt(a , n , 500000004); for(i = 0 ; i < n ; i ++ ) write(a[i]); fwrite(pbuf , 1 , pp - pbuf , stdout); return 0; }
相关文章推荐
- 【FWT】51Nod1773[A国的贸易]题解
- [51nod1773][A国的贸易][fwt]解题报告
- 快速沃尔什变换(FWT) 学习笔记
- 快速沃尔什变换详解(FWT)
- 51nod1773 A国的贸易
- FWT——快速沃尔什变换
- [FWT] 51nod 算法马拉松26 A. A国的贸易
- 关于快速沃尔什变换(FWT)的一点学习和思考
- 快速沃尔什变换(FWT)讲解 解决集合卷积的方法
- CSU 1911 Card Game 快速沃尔什变换(FWT)模板题
- 快速沃尔什变换FWT
- 快速沃尔什变换(FWT)讲解 解决集合卷积的方法
- 文章标题 FWT (快速沃尔什变换) 模板
- 解题报告:CodeForces - 662C:Binary Table FWT(快速沃尔什变换)
- 快速沃尔什变换 FWT
- Codeforces 662C Binary Table 快速沃尔什变换(FWT)
- [FWT] 51Nod 算法马拉松26 A A国的贸易
- 一个数学不好的菜鸡的快速沃尔什变换(FWT)学习笔记
- HDU 5977 Garden of Eden (树形dp+快速沃尔什变换FWT)
- 快速沃尔什变换(FWT)讲解+模板