[51nod1773][FWT]A国的贸易

版权声明:蒟蒻写的..能不能吱一声呀 https://blog.csdn.net/Rose_max/article/details/83792807

Description

A国是一个神奇的国家。
这个国家有
2
n
2n 个城市,每个城市都有一个独一无二的编号 ,编号范围为0~
2
n
2n-1。
A国的神奇体现在,他们有着神奇的贸易规则。
当两个城市u,v的编号满足calc(u,v)=1的时候,这两个城市才可以进行贸易(即有一条边相连)。
而calc(u,v)定义为u,v按位异或的结果的二进制表示中数字1的个数。
ex:calc(1,2)=2 ——> 01 xor 10 = 11
calc(100,101)=1 ——> 0110,0100 xor 0110,0101 = 1
calc(233,233)=0 ——> 1110,1001 xor 1110,1001 = 0
每个城市开始时都有不同的货物存储量。
而贸易的规则是:
每过一天,可以交易的城市之间就会交易一次。
在每次交易中,当前城市u中的每个货物都将使所有与当前城市u有贸易关系的城市货物量 +1 。
请问 t 天后,每个城市会有多少货物。
答案可能会很大,所以请对1e9+7取模。

Input

第一行两个正整数 n , t,意义如题。
第二行 2^n 个非负整数,第 i 个数表示编号为 i-1 的城市的初始货物存储量。
n<=20 t<=10^9

Output

输出一行 2^n 个非负整数。
第 i 个数表示过了 t 天后,编号为 i-1 的城市上的货物数量对 1e9+7 取模的结果。

Sample Input

样例1:
3 2
1 2 3 4 5 6 7 8
样例2:
1 1
0 1

Sample Output

样例1:
58 62 66 70 74 78 82 86
样例2:
1 1

题解

单考虑n比较小的情况,显然可以矩乘
n很大的情况不能矩乘了,但我们可以推出另外一个算法
对于一个值 x x
不妨设当前货物数是 f [ x ] f[x]
显然他一次转移是
f [ x ] + i f [ x 2 i ] f[x]+\sum_{i}f[x\oplus2^i]
构造一个多项式使得他只有在 0 , 2 i 0,2^i 位置为1
卷积一次就是下一个答案了
快速幂+ F W T FWT 即可

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define mod 1000000007
#define inv2 500000004 
using namespace std;
inline int read()
{
	int f=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int stack[20];
inline void write(int x)
{
    if(!x){putchar('0');return;}
    int top=0;
    while(x)stack[++top]=x%10,x/=10;
    while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
const int MAXNLEN[22]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152};
inline void ad(int &u,int x,int y){u=x+y;if(u>=mod)u-=mod;}
inline void dl(int &u,int x,int y){u=x-y;if(u<0)u+=mod;}
inline void fwt_xor(int *y,int len,int on)
{
	for(int i=1;i<len;i<<=1)
		for(int j=0;j<len;j+=(i<<1))
			for(int k=0;k<i;k++)
			{
				int u=y[j+k],v=y[j+k+i];
				ad(y[j+k],u,v);dl(y[j+k+i],u,v);
//				y[j+k]=(u+v)%;
//				y[j+k+i]=(u-v+mod)%mod;
				if(on==-1)y[j+k]=1LL*y[j+k]*inv2%mod,y[j+k+i]=1LL*y[j+k+i]*inv2%mod;
			}
}
int pow_mod(int a,int b)
{
	int ret=1;
	while(b)
	{
		if(b&1)ret=1LL*ret*a%mod;
		a=1LL*a*a%mod;b>>=1;
	}
	return ret;
}
int A[1100000],B[1100000],n,T;
int main()
{
//	freopen("a.in","r",stdin);
//    freopen("b.out","w",stdout);
//	int tx=clock();
	n=read();T=read();n=MAXNLEN[n];
	for(int i=0;i<n;i++)scanf("%d",&A[i]);
	B[0]=1;
	for(int i=0;MAXNLEN[i]<=n;i++)B[MAXNLEN[i]]=1;
	fwt_xor(A,n,1);fwt_xor(B,n,1);
	for(int i=0;i<n;i++)A[i]=1LL*A[i]*pow_mod(B[i],T)%mod;
	fwt_xor(A,n,-1);
//	int ty=clock();pr1(ty-tx);
	for(int i=0;i<n;i++)pr1(A[i]);
	return 0;
}


猜你喜欢

转载自blog.csdn.net/Rose_max/article/details/83792807