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

2 篇文章 0 订阅

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 x
不妨设当前货物数是 f [ x ] f[x] f[x]
显然他一次转移是
f [ x ] + ∑ i f [ x ⊕ 2 i ] f[x]+\sum_{i}f[x\oplus2^i] f[x]+if[x2i]
构造一个多项式使得他只有在 0 , 2 i 0,2^i 0,2i位置为1
卷积一次就是下一个答案了
快速幂+ F W T FWT 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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单片微型计算机(MCU)经过多年的发展,在性能上有很大的进步,在型号上发展到上千种类,已经广泛应用于人类社会生活的各个领域。单片机课程已经成为高校计算机、自动化、测控以及电子信息工程等专业的重要课程。该课程是一门理论性和实践性都很强的课程,在实际教学中,应将理论教学和实验教学紧密结合。学生在掌握理论知识之余,必须通过编写程序、设计硬件电路、仿真、调试这一系列的实验过程,才能更好地掌握单片机的结构原理和应用技能。随着单片机及其接口技术的飞速发展,目前市场上供应的编程仿真实验资源并不能完全满足高校单片机课程教与学的需求,构建低成本、技术先进、源码公开的单片机编程仿真实验系统,对我单片机课程的教学和单片机领域人才的培养具有重要的现实意义。 本论文结合目前教学中对单片机编程仿真实验系统的实际需求,采用模块化结构设计思想,精心设计和开发了单片机编程仿真实验系统。该单片机编程仿真实验系统由PC机端单片机编程控制软件和单片机编程仿真实验板两部分组成。PC机端的单片机编程控制软件可以自动检测到连接到单片机编程仿真实验板上的单片机,控制单片机编程器擦除、写入、读出、校验目标单片机ROM中的程序,以十六进制文件(.HEX文件)格式显示在控制界面内;单片机仿真实验系统能够把写入单片机的程序实时地运行,并呈现实际运行效果。单片机编程控制软件和单片机仿真实验板组成一个完整的单片机编程仿真实验系统。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值