HDU 6057 Kanade's convolution
来源:互联网 发布:VB 十六进制转rgb 编辑:程序博客网 时间:2024/06/07 06:48
HDU 6057 Kanade’s convolution
原题连接:
http://acm.hdu.edu.cn/showproblem.php?pid=6057
对于这一题
计算:
Ck=∑i and j=kAi xor jBi or j
令:
and 可以理解为交集,or 可以理解为并集,xor 可以理解为交集在并集中的补集。
这里的集合是指,2 进制形式,每一位取或者不取的情况。
1为取,0为不取。
下面为们把所有整数看作二进制集合。逻辑运算分别对应相应对,集合运算。
xor 并-交
or 并
and 交
令 x=i xor j , y=i or j
由上文并交补的关系有下面等价关系:
i and j=k <−>x and y=x 且 y−x=k
对于给定 x , y , 有多少满足x 与y 的有序对 (i,j) 呢
因为 ,i and j=k , x=i xor j , y=i or j
所以 x and k=0 ,x or k=y
这也就是说。x 与k 对立
x 是由xor 得来。
x 中对元素要么属于i 要么属于j ,不同时成立
记x 中元素数量为 bit(x) , 那么满足,x,y 关系的有序对数量为:
∑i=0(bit(x)i)=2bit(x)
所以:
Ck=∑x∑y[x and y=x][y−x=k]2bit(x)AxBy
因为 x ,k 对立。所以:x xor y=k
Ck=∑x xor y=k[y−x=k]2bit(x)AxBy
因为k=x xor y 时。
当且仅当bit(y)−bit(x)=bit(k) 时,x,k 对立。
所以:
Ck=∑x xor y=k[bit(y)−bit(x)=bit(k)]2bit(x)AxBy
定义一种数列运算F() 有:
F(A,k)是一种新数列
并且有:
F(A,k)i=[bit(i)=k]∗Ai
上面的操作其实是吧 一个数列拆成了若干序列。
按照下标二进制1 的数量拆分。
通过FWT 得到类似FFT 的点值表达
既然是点值表达,那么 加 减 乘 就很随意了。
然后通过FWT(F(A,k)),FWT(F(B,k)) 得到FWT(F(C,k))
(通过点值表达 进行 乘法,加法)
则:
Ck=F(C,bit(k))k
#include <stdio.h>#include <string.h>#include <algorithm>#define MAXN 600000using namespace std;typedef long long LL;const LL mod =998244353;LL Pow(LL a,LL b){ LL tmp=1; a%=mod; while(b) { if(b&1) tmp=tmp*a%mod; a=a*a%mod; b>>=1; } return tmp;}const LL I2=Pow(2,mod-2);void FWT(LL y[],int l,int r){ if(l==r)return; int mid=1+((l+r)>>1); FWT(y,l,mid-1); FWT(y,mid,r); for(int i=l,j=mid;i<mid;i++,j++) { LL u=y[i]; LL t=y[j]; y[i]=u+t; if(y[i]>=mod)y[i]-=mod; y[j]=u-t; if(y[j]<0) y[j]+=mod; }}void IFWT(LL y[],int l,int r){ if(l==r)return ; int mid=1+((l+r)>>1); for(int i=l,j=mid;i<mid;i++,j++) { LL u=y[i]; LL t=y[j]; y[i]=(u+t)*I2%mod; y[j]=(u-t+mod)*I2%mod; } IFWT(y,l,mid-1); IFWT(y,mid,r);}LL bit[MAXN];LL A[23][MAXN];LL B[23][MAXN];LL C[23][MAXN];LL ds[25];int main (){ LL a; int m; scanf("%d",&m); int len=1<<(m++); for(int i=0;i<len;i++) bit[i]=bit[i>>1]+(i&1); for(int i=0;i<len;i++) { scanf("%lld",&a); A[bit[i]][i]=(a*(1<<bit[i]))%mod; } for(int i=0;i<len;i++) scanf("%lld",B[bit[i]]+i); for(int i=0;i<m;i++) FWT(A[i],0,len-1); for(int i=0;i<m;i++) FWT(B[i],0,len-1); for(int i=0;i<m;i++) for(int j=i;j<m;j++) for(int t=0;t<len;t++) C[j-i][t]=(C[j-i][t]+A[i][t]*B[j][t])%mod; for(int i=0;i<m;i++) IFWT(C[i],0,len-1); LL ans=0,base=1; for(int i=0;i<len;i++) { ans=(ans+C[bit[i]][i]*base)%mod; base=base*1526%mod; } printf("%lld\n",ans); return 0;}
阅读全文
1 0
- HDU 6057 Kanade's convolution
- HDU 6057 Kanade's convolution(FWT)
- HDU-6057 Kanade's convolution(多项式FWT)
- Kanade's sum HDU
- HDU-6058 Kanade's sum
- hdu 6058 Kanade's sum
- hdu 6058 Kanade's sum
- hdu 6058 Kanade's sum
- hdu 6058 Kanade's sum
- hdu 6058 Kanade's sum
- [HDU]6058 Kanade's sum
- hdu 6058 Kanade's sum
- hdu--6058Kanade's sum
- Kanade's sum HDU 6058
- HDU 6059 Kanade's trio
- [HDU]6059 Kanade's trio
- HDU 6059 Kanade's trio
- HDU 6058 Kanade's sum
- 学习小程序整理
- Mac 终端登录mysql
- 从安装 centos 到运行 laravel
- 关于栈帧
- WebView的使用
- HDU 6057 Kanade's convolution
- 【运维业务】关于服务的SLA
- 小程序切换另一个项目
- Spring MVC 框架搭建及详解
- 为什么我越来越喜欢画低保真原型?
- 模板 Dijkstra
- Android零基础入门第24节:自定义View简单使用
- java cp命令
- C++ 后台服务器 基本面试题型