51nod1773 A国的贸易
基准时间限制:2 秒 空间限制:524288 KB 分值: 40
A国是一个神奇的国家。
这个国家有 2n 个城市,每个城市都有一个独一无二的编号 ,编号范围为0~2n-1。
ex:calc(1,2)=2 ——> 01 xor 10 = 11
每个城市开始时都有不同的货物存储量。
A国的神奇体现在,他们有着神奇的贸易规则。
当两个城市u,v的编号满足calc(u,v)=1的时候,这两个城市才可以进行贸易(即有一条边相连)。
而calc(u,v)定义为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取模。
请问 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 取模的结果。
Input示例
样例1:
3 2
1 2 3 4 5 6 7 8
样例2:
1 1
0 1
Output示例
样例1:
58 62 66 70 74 78 82 86
样例2:
1 1
动态规划 FWT
根据题意一天到下一天的转移有两种:
1、从f[x]转移到f[x](累加自身)
2、从f[x]转移到f[x Xor 2^i]
转化一下视角,从上一天到这天的转移有两种:
1、从f[x Xor 2^0]到f[x]
2、从f[x Xor 2^i]到f[x]
显然,我们构造一个数组B,使得B只有0和2的幂次位为1,其他位为0,和原数组做异或卷积就能得到一次转移的结果。
加个快速幂就可以了。
需要输出优化。
博主不知道是有多困(chun),才能做到FWT的时候只变换原数组不变换B数组就直接乘,还如同星际选手一般地反复在其他地方找bug……
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #define LL long long 7 using namespace std; 8 const int mod=1e9+7; 9 const int inv2=500000004; 10 const int mxn=2330010; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 void write(int x){ 18 if(x>9)write(x/10); 19 putchar('0'+x%10); 20 return; 21 } 22 int N,len; 23 int a[mxn],b[mxn]; 24 void FWT(int *a){ 25 for(int i=1;i<N;i<<=1){ 26 int p=i<<1; 27 for(int j=0;j<N;j+=p){ 28 for(int k=0;k<i;k++){ 29 int x=a[j+k],y=a[j+k+i]; 30 a[j+k]=(x+y);if(a[j+k]>=mod)a[j+k]-=mod; 31 a[j+k+i]=(x-y);if(a[j+k+i]<0)a[j+k+i]+=mod; 32 } 33 } 34 } 35 return; 36 } 37 void UTF(int *a){ 38 for(int i=1;i<N;i<<=1){ 39 int p=i<<1; 40 for(int j=0;j<N;j+=p){ 41 for(int k=0;k<i;k++){ 42 int x=a[j+k],y=a[j+k+i]; 43 a[j+k]=(x+y)*(LL)inv2%mod; 44 a[j+k+i]=(x-y)*(LL)inv2%mod; 45 } 46 } 47 } 48 return; 49 } 50 int ksm(int a,int k){ 51 int res=1; 52 while(k){ 53 if(k&1)res=(LL)res*a%mod; 54 a=(LL)a*a%mod; 55 k>>=1; 56 } 57 return res; 58 } 59 int n,m,T; 60 int main(){ 61 int i,j; 62 n=read();T=read(); 63 m=1<<n; 64 for(N=1,len=0;N<=m;N<<=1)len++; 65 for(i=0;i<m;i++)a[i]=read(); 66 for(i=0;i<m;i++){ 67 if(i-(i&-i)==0)b[i]=1; 68 } 69 FWT(a);FWT(b); 70 for(i=0;i<N;i++)a[i]=(LL)a[i]*ksm(b[i],T)%mod; 71 UTF(a); 72 for(i=0;i<m;i++){ 73 // printf("%d ",(a[i]+mod)%mod); 74 write((a[i]+mod)%mod); 75 putchar(' '); 76 } 77 return 0; 78 }
基准时间限制:2 秒 空间限制:524288 KB 分值: 40 难度:4级算法题
收藏
关注
A国是一个神奇的国家。
这个国家有 2n 个城市,每个城市都有一个独一无二的编号 ,编号范围为0~2n-1。
ex:calc(1,2)=2 ——> 01 xor 10 = 11
每个城市开始时都有不同的货物存储量。
A国的神奇体现在,他们有着神奇的贸易规则。
当两个城市u,v的编号满足calc(u,v)=1的时候,这两个城市才可以进行贸易(即有一条边相连)。
而calc(u,v)定义为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取模。
请问 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 取模的结果。
Input示例
样例1: 3 2 1 2 3 4 5 6 7 8 样例2: 1 1 0 1
Output示例
样例1: 58 62 66 70 74 78 82 86 样例2: 1 1
本文为博主原创文章,转载请注明出处。