P1224 [NOI2013]向量内积
发现这个内积和矩乘有点像,考虑构造一个 $n$ 行 $m$ 列的矩阵 $A$,每一行都是一个题目给定的 $m$ 维向量
设 $B=AA^T$ ,其中 $A^T$ 为 $A$ 的转置矩阵,那么对于 $B_{i,j}$ 的值,它其实就是向量 $i$ 和向量 $j$ 的内积
注意到 $K$ 只有 $2$ 或 $3$,先考虑 $K=2$ 时的情况
此时就是问矩阵 $B$ 在模 $2$ 意义下是否有位置的值为 $0$ ,并且求出位置
首先判断是否有 $0$ ,因为此时 $B$ 的元素不是 $0$ 就是 $1$ ,所以就是比较 $B$ 和全 $1$ 矩阵 $C$ 是否相等
所以就是要快速判断 $AA^T=C$ ,至于快速判断矩阵乘积结果是否等于给定矩阵,是有套路的
设 $D$ 为 $1$ 行 $n$ 列的随机矩阵,那么如果 $DAA^T \neq DC$ 那么显然 $AA^T \neq C$,否则还有概率是因为 $D$ 的影响才相等,我们多做几次判断即可
这样矩乘的复杂度就会低很多,判断 $DAA^T$ 是否等于 $DC$ 时,如果 $DC$ 的第 $i$ 个位置和 $DAA^T$ 不相等,那么说明向量 $i$ 和某个向量内积不是 $K$ 的倍数,此时我们只要枚举另一个向量 $j$ 并暴力判断即可
对于 $K=3$ 的情况,发现 $B$ 的元素不只是 $0,1$ 还有 $2$ ,似乎没法判断了
但是注意到(我也不知道怎么注意到的) $2^2 \equiv 1 \mod 3,1^2 \equiv 1 \mod 3,0^2 \equiv 0 \mod 3$
所以如果我们能把 $B$ 的每个元素平方,那么 $B$ 就又变成了 $01$ 矩阵,直接枚举元素再平方显然会 $T$ 飞
所以写写式子, $B_{i,j}=A_i \cdot A_j=\sum_{k=1}^{m}A_{i,k} \cdot A_{j,k}$,$(B_{i,j})^2=(\sum_{k=1}^{m}A_{i,k} \cdot A_{j,k})(\sum_{k=1}^{m}A_{i,k} \cdot A_{j,k})$
$(B_{i,j})^2=\sum_{k_1=1}^{m}\sum_{k2=1}^{m}(A_{i,k_1}A_{i,k_2})(A_{j,k_1}A_{j,k_2})$
所以我们把向量变成 $m^2$ 维,$A'_{i,(k_1-1)*m+k_2}=A_{i,k_1} \cdot A_{i,k_2}$
然后就可以用同样的方法判断了,当然 $A'$ 不能直接生成,我们只能存一下 $x=(k_1-1)*m+k_2$ 时的 $k_1,k_2$ 乘的时候再利用 $A_{i,k_1},A_{i,k_2}$ 进行计算
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=1e5+,M=;
int n,m,K;
inline int fk(int x) { return x>=K ? x-K : x; }
int A[N][M],B[N],C[N],D[N];
inline bool check(int i,int j)
{
int res=;
for(int k=;k<=m;k++)
res=fk(res+A[i][k]*A[j][k]%K);
return res==;
}
inline int find(int p)
{
for(int i=;i<=n;i++)
if(i!=p&&check(i,p)) return i;
return ;
}
void solve1()
{
for(int I=;I<=;I++)
{
int tot=;
for(int i=;i<=n;i++) B[i]=rand()&,tot+=B[i];
tot%=K;
for(int i=;i<=m;i++) C[i]=;
for(int i=;i<=n;i++) D[i]=;
for(int i=;i<=m;i++)
for(int j=;j<=n;j++) C[i]+=B[j]*A[j][i];
for(int i=;i<=m;i++) C[i]%=K;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++) D[i]+=C[j]*A[i][j];
D[i]%=K; if(D[i]==tot) continue;
int x=i,y=find(i);
printf("%d %d\n",min(x,y),max(x,y));
return;
}
}
printf("-1 -1\n");
}
int l[N],r[N];
void solve2()
{
int mm=m*m;
for(int i=;i<=mm;i++)
{
int t=i/m+(i%m!=);
l[i]=t; r[i]=i-(t-)*m;
}
for(int I=;I<=;I++)
{
int tot=;
for(int i=;i<=n;i++) B[i]=rand()&,tot+=B[i];
tot%=K;
for(int i=;i<=mm;i++) C[i]=;
for(int i=;i<=n;i++) D[i]=;
for(int i=;i<=mm;i++)
for(int j=;j<=n;j++) C[i]+=B[j]*A[j][l[i]]*A[j][r[i]];
for(int i=;i<=n;i++)
{
for(int j=;j<=mm;j++) D[i]+=C[j]*A[i][l[j]]*A[i][r[j]];
D[i]%=K; if(D[i]==tot) continue;
int x=i,y=find(i);
printf("%d %d\n",min(x,y),max(x,y));
return;
}
}
printf("-1 -1\n");
}
int main()
{
srand();
n=read(),m=read(),K=read();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++) A[i][j]=read()%K;
if(K==) solve1();
else solve2();
return ;
}
P1224 [NOI2013]向量内积的更多相关文章
- luogu P1224 [NOI2013]向量内积
传送门 挺有意思的一道题 暴力60就是枚举每个向量暴力check,随机选向量就能多骗一些分 然后两个向量内积要模\(k\)为\(0\),那么如果全部不为\(0\)就不合法.先考虑\(k=2\),对于向 ...
- 洛谷 P1224 - [NOI2013] 向量内积(随机化)
洛谷题面传送门 一道很神的随机化. 首先由于我们要求向量点乘 \(\bmod k\) 的值,因此我们可以将所有 \(x_{i,j}\) 都模上 \(k\),显然该操作不影响结果正确性. 注意到这里的 ...
- 【fake题解】[NOI2013]向量内积
[fake题解][NOI2013]向量内积 做法1 大暴力.哪里不会T哪里. 做法2 所有数都%=k不影响结果.(废话 k的取值只有2和3,所以肯定是要分类讨论的.k=2肯定简单些啦. k=2 出现的 ...
- [Noi2013]向量内积
来自FallDream的博客,未经允许,请勿转载,谢谢. 两个d 维向量A=[a1,a2,...,ad]与B=[b1,b2,...,bd]的内积为其相对应维度的权值的乘积和,即: $\sum_{i=1 ...
- 3243: [Noi2013]向量内积 - BZOJ
Description 两个d 维向量A=[a1,a2,...,ad]与B=[b1,b2,...,bd]的内积为其相对应维度的权值的乘积和,即: 现有 n 个d 维向量x1,...,xn ,小喵喵想知 ...
- 【uoj121】 NOI2013—向量内积
http://uoj.ac/problem/121 (题目链接) 题意 给出${n}$个${d}$维向量,问是否有两个不同的向量的内积是${k}$的倍数. Solution 又卡了一上午常数,我弃了T ...
- bzoj 3243: [Noi2013]向量内积
Description 两个d 维向量A=[a1,a2,...,ad]与B=[b1,b2,...,bd]的内积为其相对应维度的权值的乘积和,即: 现有 n 个d 维向量x1,...,xn ,小喵喵想知 ...
- BZOJ3243/UOJ121 [Noi2013]向量内积
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- BZOJ3243 NOI2013向量内积(随机化)
考虑奇技淫巧. 首先是k=2.对向量维护一个前缀和,每次将当前向量与前缀和点乘.如果点乘结果不等于i-1&1,说明当前向量至少和之前的某个向量的数量积是2的倍数,暴力找就可以了.当然等于i-1 ...
随机推荐
- AtCoder AGC030B Tree Burning
题目链接 https://atcoder.jp/contests/agc030/tasks/agc030_b 题解 细节好题.. 首先假设第一步往右走,那么可以发现当拐弯的次数一定时路径是唯一的 于是 ...
- JAVASCRIPT试题及答案
1.用jQuery编程实现获取选中复选框值的函数abc. <body> <input type="checkbox" name="aa" va ...
- Android_(控件)Chronometer计时器
Android Chronometer(计时器) 继承TextView,显示的是某个时间点开始以及之后的时间增加 运行截图 程序结构 package com.example.administrator ...
- 生成json文件写入本地
public class Json { public static void main(String[] args) { String fullPath = null; //例如:fullPath=& ...
- spark MLlib 概念 3: 卡方分布(chi-squared distribution)
数学定义[编辑] 若k个随机变量.--.是相互独立,符合标准正态分布的随机变量(数学期望为0.方差为1),则随机变量Z的平方和 被称为服从自由度为 k 的卡方分布,记作 Definition[edit ...
- redis学习之路
cp /home/zzq/桌面/M+.txt /home/zzq/mySercet#将桌面文件下的M+.txt 复制到mySercetrm -rf M+.txt#强制递归删除M+.txt1.网络适配器 ...
- SpringMvc@RequestParam 来映射请求参数
jsp页面 <a href="springmvc/testRequestParam?username=atguigu&age=11">Test RequestP ...
- 方差分析(python代码实现)
python机器学习-乳腺癌细胞挖掘(欢迎关注博主主页,学习python视频资源,还有大量免费python经典文章) https://study.163.com/course/introduction ...
- java的replace和replaceAll
都是全部替换,只不过后者参数为正则 replaceFirst()是替换第一个
- Error-ASP.NET:The Value of property CloneFrom can not be empty string!
ylbtech-Error-ASP.NET:The Value of property CloneFrom can not be empty string! 1.返回顶部 1. “/”应用程序中的服务 ...