题目大意

  有一个 \(n\times k\) 的 01矩阵 \(C\),求有多少个 \(n\times m\) 的矩阵 \(A\) 和 \(m\times k\) 的矩阵 \(B\),满足 \(A\times B=C\)。系数对 \(2\) 取模。

  还有 \(q\) 次操作,每次会修改 \(C\) 中一行的值。

  要对每次修改后的矩阵计算答案。

  \(n,m,k,q\leq 1000\)。

题解

  可以发现,答案只跟 \(C\) 的秩有关。因为如果我们对 \(C\) 做行变换或列变换,那么就可以对 \(A\) 或 \(B\) 做同样的行变换或列变换,使得等式依然成立。

  记 \(C\) 的秩为 \(r\)。

  记 \(C_i\) 表示 \(C\) 的列向量,\(A_i\) 表示 \(A\) 的列向量。

  我们先枚举矩阵 \(A\),对于每个 \(C_i\),它都是由若干个 \(A_j\) 异或得到的,系数为 \(B_{j,i}\)。

  只有所有 \(C_i\) 都在 \(A_j\) 生成的线性空间中时,才有合法的 \(B\)。

  若 \(A\) 的秩为 \(x\),那么 \(B\) 方案数就有 \(2^{k(m-x)}\) 种。

  我们先对所有秩为 \(r\) 的矩阵统计方案数,再除以秩为 \(r\) 的矩阵个数即可。

  枚举 \(A\) 的秩 \(x\),那么合法的 \(C\) 的每个列向量都可以由 \(A\) 的列向量组合而成,可以写成一个 \(k\times x\) 的矩阵,且这个矩阵的秩为 \(r\)。

  记 \(f_{i,j}\) 表示 \(n\times i\) 的秩为 \(j\) 的矩阵个数,\(p_{i,j}\) 表示 \(k\times i\) 的秩为 \(j\) 的矩阵个数,那么对答案的贡献就是 \(f_{m,x}g_{x,r}2^{k(m-x)}\)。

  最后把答案除以 \(f_{k,r}\) 即可。

  先预处理出 \(f,g\),就可以在 \(O(n)\) 内回答一次询问。

  现在我们还要求 \(C\) 的秩 \(r\)。

  对于线性基中的每个向量和所有 \(0\) 向量维护这个向量是由哪些向量异或得到的。

  在删除一个向量 \(x\) 时,找到一个包含 \(x\) 的 \(0\) 向量,如果没有就找线性基里位最低的包含 \(x\) 的向量,把这个向量的信息异或到其他包含 \(x\) 的向量的信息中即可。这样在删除时不会影响线性基中更高位的向量。

  时间复杂度:\(O(\frac{(n+q)n^2}{w})\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<functional>
#include<cmath>
#include<vector>
#include<assert.h>
#include<bitset>
using namespace std;
using std::min;
using std::max;
using std::swap;
using std::sort;
using std::reverse;
using std::random_shuffle;
using std::lower_bound;
using std::upper_bound;
using std::unique;
using std::vector;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef std::pair<int,int> pii;
typedef std::pair<ll,ll> pll;
void open(const char *s){
#ifndef ONLINE_JUDGE
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
void open2(const char *s){
#ifdef DEBUG
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');}
int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
const ll p=1000000007;
const int N=1010;
ll fp(ll a,ll b)
{
ll s=1;
for(;b;b>>=1,a=a*a%p)
if(b&1)
s=s*a%p;
return s;
}
typedef bitset<N> orzzjt;
typedef pair<orzzjt,orzzjt> zjtakioi2019;
ll pw[N*N];
ll f[N][N],g[N][N];
void add(ll &a,ll b)
{
a=(a+b)%p;
}
int n,m,k;
ll solve(int x)
{
ll res=0;
for(int i=x;i<=n&&i<=m;i++)
res=(res+f[m][i]*g[i][x]%p*pw[k*(m-i)])%p;
res=res*fp(f[m][x],p-2)%p;
res=(res%p+p)%p;
return res;
}
ll e[N];
void init()
{
pw[0]=1;
for(int i=1;i<=1000000;i++)
pw[i]=pw[i-1]*2%p;
f[0][0]=1;
for(int i=0;i<1000;i++)
for(int j=0;j<=i&&j<=n;j++)
if(f[i][j])
{
add(f[i+1][j],f[i][j]*pw[j]);
add(f[i+1][j+1],f[i][j]*(pw[n]-pw[j]));
}
g[0][0]=1;
for(int i=0;i<1000;i++)
for(int j=0;j<=i&&j<=k;j++)
if(g[i][j])
{
add(g[i+1][j],g[i][j]*pw[j]);
add(g[i+1][j+1],g[i][j]*(pw[k]-pw[j]));
}
for(int i=0;i<=n&&i<=k;i++)
e[i]=solve(i);
}
zjtakioi2019 a[N];
orzzjt b[N];
int t;
int r;
void insert(orzzjt x,int v)
{
orzzjt y;
y.set(v);
for(int i=1000;i>=1;i--)
if(x[i])
{
if(!a[i].first.any())
{
a[i].first=x;
a[i].second=y;
r++;
return;
}
x^=a[i].first;
y^=a[i].second;
}
t++;
b[t]=y;
}
void erase(int x)
{
for(int i=1;i<=t;i++)
if(b[i][x])
{
swap(b[i],b[t]);
t--;
for(int j=1;j<=1000;j++)
if(a[j].second[x])
a[j].second^=b[t+1];
for(int j=1;j<=t;j++)
if(b[j][x])
b[j]^=b[t+1];
return;
}
for(int i=1;i<=1000;i++)
if(a[i].second[x])
{
for(int j=i+1;j<=1000;j++)
if(a[j].second[x])
{
a[j].first^=a[i].first;
a[j].second^=a[i].second;
}
a[i].first=a[i].second=orzzjt();
r--;
return;
}
}
int main()
{
open("c");
int q,type;
scanf("%d%d%d%d%d",&n,&m,&k,&q,&type);
init();
int x,y;
for(int i=1;i<=n;i++)
{
orzzjt s;
for(int j=1;j<=k;j++)
{
scanf("%d",&x);
if(x)
s.set(j);
}
insert(s,i);
}
ll ans=e[r];
printf("%lld\n",ans);
for(int i=1;i<=q;i++)
{
scanf("%d",&x);
x^=type*ans;
erase(x);
orzzjt s;
for(int j=1;j<=k;j++)
{
scanf("%d",&y);
if(y)
s.set(j);
}
insert(s,x);
ans=e[r];
printf("%lld\n",ans);
}
return 0;
}

【UOJ453】【集训队作业2018】围绕着我们的圆环 线性基 DP的更多相关文章

  1. UOJ #449. 【集训队作业2018】喂鸽子

    UOJ #449. [集训队作业2018]喂鸽子 小Z是养鸽子的人.一天,小Z给鸽子们喂玉米吃.一共有n只鸽子,小Z每秒会等概率选择一只鸽子并给他一粒玉米.一只鸽子饱了当且仅当它吃了的玉米粒数量\(≥ ...

  2. [UOJ422][集训队作业2018]小Z的礼物——轮廓线DP+min-max容斥

    题目链接: [集训队作业2018]小Z的礼物 题目要求的就是最后一个喜欢的物品的期望得到时间. 根据$min-max$容斥可以知道$E(max(S))=\sum\limits_{T\subseteq ...

  3. 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)

    [UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...

  4. 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)

    [UOJ#422][集训队作业2018]小Z的礼物(min-max容斥,轮廓线dp) 题面 UOJ 题解 毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ 一开始开错题了,根本就不会做. 后来发现是每次 ...

  5. UOJ#418. 【集训队作业2018】三角形

    #418. [集训队作业2018]三角形 和三角形没有关系 只要知道儿子放置的顺序,就可以直接模拟了 记录历史最大值 用一个pair(a,b):之后加上a个,期间最大值为增加b个 合并? A1+A2= ...

  6. 2019.2.25 模拟赛T1【集训队作业2018】小Z的礼物

    T1: [集训队作业2018]小Z的礼物 我们发现我们要求的是覆盖所有集合里的元素的期望时间. 设\(t_{i,j}\)表示第一次覆盖第i行第j列的格子的时间,我们要求的是\(max\{ALL\}\) ...

  7. [集训队作业2018]蜀道难——TopTree+贪心+树链剖分+链分治+树形DP

    题目链接: [集训队作业2018]蜀道难 题目大意:给出一棵$n$个节点的树,要求给每个点赋一个$1\sim n$之内的权值使所有点的权值是$1\sim n$的一个排列,定义一条边的权值为两端点权值差 ...

  8. UOJ#422. 【集训队作业2018】小Z的礼物

    #422. [集训队作业2018]小Z的礼物 min-max容斥 转化为每个集合最早被染色的期望时间 如果有x个选择可以染色,那么期望时间就是((n-1)*m+(m-1)*n))/x 但是x会变,中途 ...

  9. UOJ#428. 【集训队作业2018】普通的计数题

    #428. [集训队作业2018]普通的计数题 模型转化好题 所以变成统计有标号合法的树的个数. 合法限制: 1.根标号比子树都大 2.如果儿子全是叶子,数量B中有 3.如果存在一个儿子不是叶子,数量 ...

随机推荐

  1. tensorflow用pretrained-model做retrain

    最近工作里需要用到tensorflow的pretrained-model去做retrain. 记录一下. 为什么可以用pretrained-model去做retrain 这个就要引出CNN的本质了.C ...

  2. 树莓派linux系统连接windows7系统中的共享文件夹的正确姿势

    一.要想使用树莓派linux成功访问win7的共享文件夹而不报错,最重要的事情是要正确设置win7中共享文件的设置. 1.需要共享文件点击右键→属性 2.共享选项卡→网络和共享中心 3.点开公用下拉菜 ...

  3. 使用wepy开发微信小程序01——常用的组件

    1.axio.js 'use strict' import axios from 'axios' import wepyAxiosAdapter from 'wepy-plugin-axios/dis ...

  4. harris角点检测的简要总结

    目录 1. 概述相关 2. 原理详解 1) 算法思想 2) 数学模型 3) 优化推导 3. 具体实现 1) 详细步骤 2) 最终实现 4. 参考文献 1. 概述相关 harris角点检测是一种特征提取 ...

  5. Microsoft SQL Server 2016 RC3 安装

    首先下载SQL Server 2016 RC3 安装iso 下载链接 ed2k://|file|cn_sql_server_2016_rc_3_x64_dvd_8566578.iso|24648232 ...

  6. SQLServer创建用户登录

    创建用户登录注意事项 密码是区分大小写的. 只有创建SQL Server登录时,才支持对密码预先进行哈希运算. 如果指定MUST_CHANGE,则CHECK_EXPIRATION和 CHECK_POL ...

  7. Microsoft Deployment Toolkit build 8456

    MDT build 8456的重大变化摘要. 支持的配置更新 Windows ADK for Windows 10,版本1809 Windows 10,版本1809 Configuration Man ...

  8. 64位Win7下Asp.net项目连接Oracle时报ORA-6413:连线未打开异常

    当时小弟碰到这个问题的时候,也找了挺久的回答,但是回答都是模棱两可的说是因为()的问题,但是没有给出具体的解决方案,这里小弟就用一个比较笨的方法来解决这个问题. 第一种:就是使用本地IISWeb服务器 ...

  9. Vue-cli在webpack内使用雪碧图(响应式)

    先执行install cnpm install webpack-spritesmith 文件位置 build\webpack.dev.conf.js 添加内容: const SpritesmithPl ...

  10. C#二维码与条形码的生成

    二维码 using Gma.QrCodeNet.Encoding;using Gma.QrCodeNet.Encoding.Windows.Render; string str = "Htt ...