当前位置: 首页 > news >正文

FWT+高维前缀和:Gym - 103202M

https://vj.imken.moe/contest/597216#problem/F

考虑两个人的集合分别为 i , j i,j i,j,那么我们令 f ( i ⊗ j ) + + f(i\otimes j)++ f(ij)++,其中 f ( s ) f(s) f(s) 表示两个人不同集合恰好 s s s,显然 f ( s ) f(s) f(s) 可以FWT求。

假设 g ( t ) g(t) g(t) 表示选集合为 t t t 有多少个不同的对数,显然有 g ( t ) = ∑ s & j ≠ ∅ f ( s ) = n ( n − 1 ) 2 − ∑ s ⊆ U − t f ( s ) g(t)=\sum_{s\& j\neq \empty}f(s)=\frac {n(n-1)}2-\sum_{s\subseteq U-t}f(s) g(t)=s&j=f(s)=2n(n1)sUtf(s),因此我们对 f f f 做一遍高维前缀和即可。

#include<bits/stdc++.h>
using namespace std;
#ifdef LOCAL#define debug(...) fprintf(stdout, ##__VA_ARGS__)
#else#define debug(...) void(0)
#endif
#define int long long
inline int read(){int x=0,f=1;char ch=getchar(); while(ch<'0'||
ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
#define fi first
#define se second
//srand(time(0));
#define N 2000010
//#define M
//#define mo
int n, m, i, j, k, T;
int g[N], a[N], ans; 
char str[N]; struct FWT {int f[N], n, o, i, j, k; void XOR(int x) {for(k=1, o=2; o<=n; o<<=1, k<<=1) {for(i=0; i<n; i+=o) for(j=0; j<k; ++j) {f[i+j]+=f[i+j+k]; f[i+j+k]=f[i+j]-2*f[i+j+k]; if(x==-1) f[i+j]/=2, f[i+j+k]/=2;  }}}void Mul() {for(i=0; i<n; ++i) f[i]*=f[i]; }void work(int p) {f[0]-=p; for(i=0; i<n; ++i) f[i]/=2; }
}fwt;signed main()
{#ifdef LOCALfreopen("in.txt", "r", stdin);freopen("out.txt", "w", stdout);#endif
//	T=read();
//	while(T--) {
//
//	}n=read(); m=read(); k=read(); fwt.n=(1<<m); for(i=1; i<=n; ++i) {scanf("%s", str+1); for(j=1; j<=m; ++j) if(str[j]=='B') a[i]|=(1<<j-1); fwt.f[a[i]]++; }fwt.XOR(1); fwt.Mul(); fwt.XOR(-1); fwt.work(n); for(i=0; i<(1<<m); ++i) g[i]=fwt.f[i]; for(i=0; i<(1<<m); ++i) debug("%lld ", g[i]); debug("\n"); for(j=0; j<m; ++j)for(i=0; i<(1<<m); ++i) if(i&(1<<j)) g[i]+=g[i-(1<<j)]; for(i=0; i<(1<<m); ++i) debug("%lld ", g[i]); debug("\n"); for(i=0; i<(1<<m); ++i) if(i<(1<<m)-i) swap(g[i], g[(1<<m)-1-i]); for(i=0; i<(1<<m); ++i) debug("%lld ", g[i]); debug("\n"); for(i=1; i<(1<<m); ++i) g[i]=n*(n-1)/2-g[i]; for(i=1; i<(1<<m); ++i) if(g[i]>=k) ++ans; printf("%lld", ans); return 0;
}
http://www.lryc.cn/news/250542.html

相关文章:

  • 【C++】string类的接口综合运用
  • 分布式ID生成框架Leaf升级踩坑
  • 常用的设计模式
  • git的相关实用命令
  • 【使用`model.status`来获取gurobi求解过程中的模型状态】
  • 【UGUI】Unity教程:实现物品的拖拽功能
  • 【奇淫技巧】两数交换
  • Java核心知识点整理大全26-笔记
  • “上云”还是“下云”?探云计算的下一站未来!
  • Linux中top命令输出日志分析?
  • 执行栈和执行上下文
  • 7、单片机与W25Q128(FLASH)的通讯(SPI)实验(STM32F407)
  • stream流和方法引用
  • Redis——某马点评day01——短信登录
  • AES加密技术:原理与应用
  • Unity中PlayerPrefs在PC上存储位置总结
  • 消融实验:深度学习的关键分析工具
  • Redis缓存——Spring Cache入门学习
  • Python标准库copy【侯小啾python领航班系列(十五)】
  • Android--Jetpack--Lifecycle详解
  • LeetCode105.从前序和中序遍历序列构造二叉树
  • flutter-一个可以输入的数字增减器
  • 抑郁症中西医治疗对比?
  • 012 OpenCV sobel边缘检测
  • 【开源视频联动物联网平台】libmodbus 写一个modbus tcp客户端
  • 安装以及使用 stylepro_artistic 所遇问题解决
  • 【Rust】所有权的认识
  • 中间件安全:Weblogic 漏洞.(使用工具可以利用多种类型漏洞)
  • matlab操作方法(一)——向量及其操作
  • MicroPython标准库