原文链接www.cnblogs.com/zhouzhendong/UOJ121.html

前言

完蛋了我越来越菜了贺题都不会了。

题解

\(O(n ^ 2 d)\) 暴力送 60 分。

Bitset 优化一下说不定更稳。可能有 85 分。

来讲正解。

注意下文中的 "p" 表示原题中的 "k"。

首先我们来解决一个问题:

如何在较低的复杂度下判定矩阵 A,B,C 是否满足 \(A\times B = C\) 。

做法是:随机 O(1) 个行向量 \(x\),判定 \(x \times A \times B = x\times C\) 是否成立。本题中,行向量大概只需要 10 个左右。

回到本题。

考虑 p = 2 的情况。设矩阵 A 为 \(n \times d\) 的矩阵,且满足 \(A_{i,j} = x_{i,j}\) ,设矩阵 \(B = A ^ {T}\) 。

\[self_ i = \sum_{j = 1} ^ d A_{i,j} B_{j,i}
\]

那么,如果无解,则

\[A \times B =
\begin{bmatrix}
self_1 & 1 & 1 & 1 & \cdots & 1 \\
1 & self_2 & 1 & 1 & \cdots & 1 \\
1 & 1 & self_3 & 1 & \cdots & 1 \\
1 & 1 & 1 & self_4 & \cdots & 1 \\
\vdots & \vdots &\vdots &\vdots &\ddots & \vdots\\
1 & 1 & 1 & 1 & \cdots & self_n
\end{bmatrix}
\]

所以,我们可以利用之前提到的方法在 \(O(nd)\) 的时间复杂度内判定是否有解。如果算出来的行向量的第 \(i\) 项前后不等,那么第 \(i\) 个向量和某一个向量的内积一定模p为0。

当 p = 3 时,考虑到最终矩阵很难确定,因为模 3 意义下可能是 1 或 2。

但是由于 \(1 ^ 2 \equiv 2 ^ 2 \equiv 1 \pmod 3\),所以我们可以考虑取平方。

可以发现

\[\left ( \sum _k A_{i,k} B_{k,j} \right ) ^ 2 = \sum_{k_1} \sum_{k_2} \left ( A_{i,k_1} A_{i,k_2}\right) \left ( B_{i,k_1} B_{i,k_2}\right )
\]

所以我们可以改写矩阵的定义,设矩阵 \(A'\) 为一个由 \([1\cdots n]\) 映射到 \((k_1,k_2) | k_1\in [1\cdots d] , k_2 \in [1\cdots d]\) 的矩阵,矩阵 \(B'\) 为一个由 \((k_1,k_2) | k_1\in [1\cdots d] , k_2 \in [1\cdots d]\) 映射到 \([1\cdots n]\) 的矩阵。

剩下的做法和原先一样。

时间复杂度为 \(O(n d ^ {p-1})\) 。

代码

#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof x)
#define For(i,a,b) for (int i=(a);i<=(b);i++)
#define Fod(i,b,a) for (int i=(b);i>=(a);i--)
#define fi first
#define se second
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define outval(x) cerr<<#x" = "<<x<<endl
#define outtag(x) cerr<<"---------------"#x"---------------"<<endl
#define outarr(a,L,R) cerr<<#a"["<<L<<".."<<R<<"] = ";\
For(_x,L,R)cerr<<a[_x]<<" ";cerr<<endl;
using namespace std;
typedef long long LL;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=100005,D=105;
int n,d,p;
int x[N][D],y[N];
int a[N][D],b[D][N];
int s[N],t[N],c[D][D];
int self[N];
int Solve(int k){
For(i,1,n)
if (i!=k){
int s=0;
For(j,1,d)
s+=x[i][j]*x[k][j];
s%=p;
if (s==0){
printf("%d %d\n",min(i,k),max(i,k));
return 1;
}
}
return 0;
}
int main(){
n=read(),d=read(),p=read();
For(i,1,n){
For(j,1,d)
x[i][j]=read()%p;
self[i]=0;
For(j,1,d)
self[i]+=x[i][j]*x[i][j];
self[i]%=p;
if (p==3)
self[i]=self[i]*self[i]%p;
}
For(i,1,n)
For(j,1,d)
a[i][j]=b[j][i]=x[i][j];
srand(233);
For(_,1,10){
int sum=0;
For(i,1,n)
y[i]=rand()%5?1:0,sum+=y[i];
if (p==2){
For(i,1,n)
s[i]=y[i];
clr(t);
For(i,1,n)
For(j,1,d)
t[j]+=s[i]*a[i][j];
For(i,1,d)
t[i]%=p;
clr(s);
For(i,1,n)
For(j,1,d)
s[i]+=t[j]*b[j][i];
For(i,1,n)
s[i]%=p;
}
else {
For(i,1,n)
s[i]=y[i];
clr(c);
For(i,1,n)
For(j1,1,d)
For(j2,1,d)
c[j1][j2]+=s[i]*a[i][j1]*a[i][j2];
For(j1,1,d)
For(j2,1,d)
c[j1][j2]%=p;
clr(s);
For(i,1,n)
For(j1,1,d)
For(j2,1,d)
s[i]+=c[j1][j2]*b[j1][i]*b[j2][i];
For(i,1,n)
s[i]%=p;
}
For(i,1,n)
t[i]=(sum-(1-self[i])*y[i])%p;
For(i,1,n)
if (s[i]!=t[i])
return assert(Solve(i)),0;
}
puts("-1 -1");
return 0;
}

UOJ#121. 【NOI2013】向量内积 随机化算法,矩阵的更多相关文章

  1. 【BZOJ-3243】向量内积 随机化 + 矩阵

    3243: [Noi2013]向量内积 Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 1249  Solved:  ...

  2. 【fake题解】[NOI2013]向量内积

    [fake题解][NOI2013]向量内积 做法1 大暴力.哪里不会T哪里. 做法2 所有数都%=k不影响结果.(废话 k的取值只有2和3,所以肯定是要分类讨论的.k=2肯定简单些啦. k=2 出现的 ...

  3. [Noi2013]向量内积

    来自FallDream的博客,未经允许,请勿转载,谢谢. 两个d 维向量A=[a1,a2,...,ad]与B=[b1,b2,...,bd]的内积为其相对应维度的权值的乘积和,即: $\sum_{i=1 ...

  4. P1224 [NOI2013]向量内积

    传送门 发现这个内积和矩乘有点像,考虑构造一个 $n$ 行 $m$ 列的矩阵 $A$,每一行都是一个题目给定的 $m$ 维向量 设 $B=AA^T$ ,其中 $A^T$ 为 $A$ 的转置矩阵,那么对 ...

  5. luogu P1224 [NOI2013]向量内积

    传送门 挺有意思的一道题 暴力60就是枚举每个向量暴力check,随机选向量就能多骗一些分 然后两个向量内积要模\(k\)为\(0\),那么如果全部不为\(0\)就不合法.先考虑\(k=2\),对于向 ...

  6. 洛谷 P1224 - [NOI2013] 向量内积(随机化)

    洛谷题面传送门 一道很神的随机化. 首先由于我们要求向量点乘 \(\bmod k\) 的值,因此我们可以将所有 \(x_{i,j}\) 都模上 \(k\),显然该操作不影响结果正确性. 注意到这里的 ...

  7. BZOJ3243 NOI2013向量内积(随机化)

    考虑奇技淫巧. 首先是k=2.对向量维护一个前缀和,每次将当前向量与前缀和点乘.如果点乘结果不等于i-1&1,说明当前向量至少和之前的某个向量的数量积是2的倍数,暴力找就可以了.当然等于i-1 ...

  8. UOJ#75. 【UR #6】智商锁 随机化算法 矩阵树定理

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ75.html 前言 根本没想到. 题解 首先我们可以考虑一种做法: 找一些图,使得他们各自的生成树个数乘起来等于 k. 那 ...

  9. 【uoj121】 NOI2013—向量内积

    http://uoj.ac/problem/121 (题目链接) 题意 给出${n}$个${d}$维向量,问是否有两个不同的向量的内积是${k}$的倍数. Solution 又卡了一上午常数,我弃了T ...

随机推荐

  1. centos7.5 离线安装ntp服务

    安装 #检查rpm包 rpm -qa | grep ntp #从https://pkgs.org/download/ntp 下载rpm包 ntp-4.2.6p5-28.el7.centos.x86_6 ...

  2. 动画处理<并行和串行>

    并行动画 当多个动画定义同时指向某个组件,并使用动画控制器启动时,就产生了并行动画(Parallel Animation).例如我们可以让一个组件: 移动的同时改变大小 旋转的同时边界颜色闪烁 圆形图 ...

  3. Eclipse - servlet显示无法导入javax.servlet包问题的解决方案

    项目名-->右键 Property-->选择 Java Build Path-->选择 Add External JARs-->选择 把servlet-api.jar的路径输入 ...

  4. Python学习日记(二十五) 接口类、抽象类、多态

    接口类 继承有两种用途:继承基类的方法,并且做出自己的改变或扩展(代码重用)和声明某个子类兼容于某基类,定义一个接口类interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子 ...

  5. 【JUC】7.CountDownLatch

    Latch:门闩.一种线程通信的方式:当程序不涉及同步,仅仅需要线程通信的时候,使用synchronize或者lock的线程通信等待唤醒机制,就显得太重了: 这时候,可以考虑使用信号量类:CountD ...

  6. SQL SERVER-Exclusive access could not be obtained because the database is in use. (Microsoft.SqlServer.SmoExtended)

    Q:先在一个实例中恢复一个数据A,然后又想在恢复一次,取别名为A2,这是报异常SQL SERVER-Exclusive access could not be obtained because the ...

  7. http状态码记录

    一些常见的状态码为: 200 - 服务器成功返回网页404 - 请求的网页不存在503 - 服务不可用详细分解: 1xx(临时响应)表示临时响应并需要请求者继续执行操作的状态代码. 代码 说明100 ...

  8. [ipsec][strongswan] VirtualPN隧道网络加速FEC(forward error correction)

    引用 跟一个网友就有关IPsec的网络加速以及降低延迟等问题进行了一些讨论,并总结了一写粗浅的看法. 因为FEC的资料并不多,所以分享出来,希望能被有需要的人看见:) 先说一下FEC. 我们使用ips ...

  9. yum源仓库的三种搭建方式

    yum源的三种搭建方式 一.  本地yum仓库的搭建 1.1.获取软件包资源 将iso镜像挂载在本地目录中,此次挂载目录为/var/www/html/repo/,此目录本身不存在,需要创建.软件宝资源 ...

  10. pip---cannot import name main解决方案

    .先来看下Python不同版本对应的路径 which python3. which python3. .使用update-alternatives --install建立链接 sudo update- ...