博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
GDOI2015的某道题目
阅读量:5093 次
发布时间:2019-06-13

本文共 2158 字,大约阅读时间需要 7 分钟。

分析:

考试的时候由于一些神奇的原因(我就不说是什么了)...没有想$C$题,直接交了个暴力上去...

然后发现暴力的数组开的太大,由于矩阵乘法的需要做$m$次初始化,所以只拿到了10分...

我们一步一步来挖掘题目中隐含的条件...

首先,这个矩阵乘法很特殊,是位运算的形式,那么也就是说,每一位的运算是独立的,所以我们可以拆位,处理每一位的运算...

然后考虑对于其中的一位如何快速计算一个矩阵的$n$次幂...考虑到每一个格子只有可能是$0$或$1$,观察发现,对于数字$a[i][j]$,只有当第$i$行和第$j$列是相同的时候,我们新的到的矩阵中$a[i][j]$才是$0$,否则因为是$or$运算,所以只要有一位不同就是$1$...

那么我们考虑$A^{m-1}*A=A^{m}$,记$X=A^{m-1}$,$Y=A^m$,我们考虑$X$的每一个行向量对应的$Y$中的行向量是什么样子的,如果当前的行向量和$A$中的任意一个列向量都相等的话,那么新得到的行向量就是一个全为$1$的向量,否则,最多只有可能有$n$种取值,现在我们假设$A$中的每一个列向量都互不相同,那么也就是说,当前的行向量只有可能有一个地方是$0$,这个$0$最多有$n$中位置...所以当前行向量所对应的结果中的行向量最多有$n+1$种取值...因为每一次我们乘上的矩阵都是相同的,所以说无论进行多少次乘法,我们都只有可能在$n+1$种取值中给行向量赋值...那么也就是说,现在我们有一个$n+1$个点的图,然后我们需要在这张图上走$m-1$步,那么就可以倍增找到答案...至于对于图的预处理我们可以用$bitset$来加速...

没有想出来的原因:

没有充分利用到位运算的性质区进行拆位,没有想到去考虑每个行向量所对应的结果是存在循环的...

代码:

一开始实在不理解怎么做所以直接抄了一遍$std$...

#include
#include
#include
#include
//by NeighThornusing namespace std;const int maxn=500+5;int n,m,tot,a[maxn][maxn],f[maxn<<1][30],id[maxn],ans[maxn][maxn];struct M{ unsigned long long a[8]; friend bool operator == (M x,M y){ for(int i=0;i<=7;i++) if(x.a[i]!=y.a[i]) return false; return true; } inline void modify(int pos,int x){ a[pos>>6]|=1ULL<<(pos&63); if(!x) a[pos>>6]^=1ULL<<(pos&63); } inline bool query(int pos){ return (a[pos>>6]>>(pos&63))&1; } }colu[maxn],node[maxn<<1];inline int build(void){ for(int i=1;i<=tot;i++) if(node[i]==node[tot+1]) return i; int res=++tot; for(int i=1;i<=n;i++) node[tot+1].modify(i,!(node[res]==colu[i])); f[res][0]=build(); return res;}signed main(void){ freopen("C.in","r",stdin); freopen("C.out","w",stdout); scanf("%d%d",&n,&m);m--; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&a[i][j]); for(int i=0;i<=30;i++){ for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) colu[j].modify(k,(a[k][j]>>i)&1); tot=0; for(int j=1;j<=n;j++){ for(int k=1;k<=n;k++) node[tot+1].modify(k,(a[j][k]>>i)&1); id[j]=build(); } for(int j=1;j<=29;j++) for(int k=1;k<=tot;k++) f[k][j]=f[f[k][j-1]][j-1]; for(int j=0;j<=29;j++) if(m&(1<

  


By NeighThorn

转载于:https://www.cnblogs.com/neighthorn/p/6696519.html

你可能感兴趣的文章
Android系统--输入系统(十一)Reader线程_简单处理
查看>>
监督学习模型分类 生成模型vs判别模型 概率模型vs非概率模型 参数模型vs非参数模型...
查看>>
Mobiscroll脚本破解,去除Trial和注册时间限制【转】
查看>>
32位与64位 兼容编程
查看>>
iframe父子页面通信
查看>>
map基本用法
查看>>
Redis快速入门
查看>>
BootStrap---2.表格和按钮
查看>>
Linear Algebra lecture 2 note
查看>>
CRC计算模型
查看>>
Ajax之404,200等查询
查看>>
Aizu - 1378 Secret of Chocolate Poles (DP)
查看>>
csv HTTP简单表服务器
查看>>
OO设计的接口分隔原则
查看>>
数据库连接字符串大全 (转载)
查看>>
java类加载和对象初始化
查看>>
对于负载均衡的理解
查看>>
django简介
查看>>
window.event在IE和Firefox的异同
查看>>
常见的js算法面试题收集,es6实现
查看>>