• 【51Nod1773】A国的贸易 FWT+快速幂


    题目描述

    给出一个长度为 $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$ 经过一次操作后得到的新序列就是 $aoplus 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[N] , b[N];
    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;
    }
    
  • 相关阅读:
    SVN操作异常
    VS2010安装MVC3
    (转)游戏类型
    (转)32位汇编指令 寄存器
    (转)#pragma 用法
    (转)UI库
    (转)简单实用的网游服务器架构
    (转)一个客户端网游市场分布的数据
    (转)源于魔兽!《植物大战僵尸》成功奥秘
    (转)【分析】中国网游行业上市公司投资分析之网易
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/8142810.html
Copyright © 2020-2023  润新知