【NOI2013】向量内积
定义两个$d$维向量${A=[a_1,a_2....a_n]}$,${B=[b_1,b_2....b_n]}$的内积为其相对应维度的权值的乘积和:
$${\left \langle A,B \right \rangle= \sum _{i=1}^{d}a_i*b_i}$$
现在有$n$个$d$维向量,判断是否存在两个向量的内积为$k$的倍数${(2\leq k\leq 3)}$
我们考虑将$n$个$d$维的向量构成一个$n*d$的矩阵$A$,$A^{T}$为$A$的转置矩阵。
令矩阵${B=A*A^{t}}$,那么${B_{i,j}}$就表示了向量$i$,与向量$j$的内积。
直接判断内积的值即可。
但是这仅仅简化了题意,复杂度仍是${O(n^{2}d)}$,大概可以得到$50$分。
考虑$k=2$的情况(矩阵的取值均在模$2$的意义下进行讨论)
我们有一种经典的方法判定两个矩阵是否相等,我们只关心$0$元素是否存在。
令$C$为全$1$矩阵
在模$2$的意义下随机一个$1*n$的向量$X$。
根据矩阵乘法的结合律判断等式${X*A*A^{T}=X*C}$是否成立。
若是存在有一个元素不相同,表示对应列上出现了一个$0$向量,然后暴力寻找行的位置即可。
若是这一次没有找到,也许是根本就没有这样的向量或者是刚好在这个$X$向量的影响下判为了相等,多做几次,每次正确率约为$0.5$。
综合暴力至此可以得到$75$分。
考虑$k=3$的情况,为什么就不能像$k=2$的时候那样做了呢?
因为矩阵$B$中的元素可以是${{0,1,2}}$了,无法再和全$1$矩阵$C$比较。
想办法将$k=3$的情况转换为$k=2$的情况。
之所以不能像$k=2$做,是因为出现了结果为$2$的情况。
注意到一个性质:${2\equiv -1\left ( mod 3 \right )}$
因此,如果我们将矩乘之后的矩阵D的所有结果平方,那么C就能用全1矩阵了。
令${NEWA\left ( i,j \right )=D(i,j)^{2}}$
${\because NEWA\left ( i,j \right )=\sum _{k_1=1}^{d}\sum _{k_2=1}^{d}A(i,k_1)A(i,k_2)A(k1,j)A(k2,j)}$
你可以想象成可以把每一个$d$维向量$A$转化为了${d^{2}}$维向量$Z$,其中${Z_{(i-1)*d+j}=a_i*a_j (1\leq i,j\leq d)}$
${\therefore }$这个时候变成了${n*d^{2}}$的矩阵与${d^{2}*n}$的矩阵相乘。
之后的做法就与$k=2$的情况相同。
综合之前的分数可以获得$100$分
NOTICE:$k=3$的运算是在模$3$的意义下的,只是最后的结果平方之后的值只能为${{0,1}}$。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<ctime>
using namespace std;
#define maxn 100100
#define maxd 310
#define llg long long
#define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
llg n,a[maxn][maxd],d,k;
llg X[maxn],NX[maxn];
llg LX[maxn],Y[maxn],LY[maxn],T,g[maxn],l[maxn],r[maxn];
llg D;
bool pd=false; void init()
{
cin>>n>>d>>k;
for (llg i=;i<=n;i++)
for (llg j=;j<=d;j++)
{
scanf("%lld",&a[i][j]);
// at[j][i]=a[i][j];
g[i]+=a[i][j]*a[i][j]; g[i]%=k;
}
} void check(llg i,llg j)
{
llg sum=;
for (llg p=;p<=d;p++) sum+=a[i][p]*a[j][p];
sum%=k;
if (sum==)
{
if (i>j) swap(i,j);
printf("%lld %lld\n",i,j);
pd=true;
}
} inline void solve2()
{
memset(LX,,sizeof(LX)); memset(NX,,sizeof(NX));
llg tot=;
for (llg i=;i<=n;i++) X[i]=rand()%k,tot+=X[i],tot%=k;
for (llg i=;i<=d;i++)
for (llg j=;j<=n;j++)
NX[i]+=X[j]*a[j][i],NX[i]%=k;
for (llg i=;i<=n;i++)
for (llg j=;j<=d;j++)
LX[i]+=NX[j]*a[i][j],LX[i]%=k;
for (llg i=;i<=n;i++)
if (LX[i]!=tot)
{
for (llg j=;j<=n;j++)
if (i!=j)
{
if (pd) return ;
check(i,j);
}
}
} void solve3()
{
memset(LX,,sizeof(LX)); memset(NX,,sizeof(NX));
llg tot=;
for (llg i=;i<=n;i++) X[i]=rand()%k,tot+=X[i];
tot%=k;
for (llg j=;j<=n;j++)
for (llg i=;i<=D;i++) NX[i]+=X[j]*a[j][l[i]]*a[j][r[i]];
for (llg i=;i<=n;i++)
{
for (llg j=;j<=D;j++) LX[i]+=NX[j]*a[i][l[j]]*a[i][r[j]];
LX[i]+=(-g[i])*X[i]; LX[i]%=k; LX[i]+=k;
if (LX[i]%k!=tot)
{
for (llg j=;j<=n;j++)
if (i!=j)
{
if (pd) return;
check(i,j);
}
llg he=;
}
}
} int main()
{
yyj("a");
srand(time(NULL));
init();
if (k==)
{
T=;
while (T--)
{
solve2();
if (pd) return ;
}
}
else
{
T=;
for (llg i=;i<=n;i++) g[i]*=g[i],g[i]%=k;
D=d*d;
for (llg i=;i<=D;i++)
{
llg t=(i%d==)?i/d:i/d+;
l[i]=t,r[i]=i-(t-)*d;
}
while (T--)
{
solve3();
if (pd) return ;
}
}
if (!pd) cout<<"-1 -1";
return ;
}
HACK(若取全1矩阵C,但C的对角线均设为了0):
${A*A^{T}}$
全${1}$向量${X}$
${A*X*A^{t}}$
${C*X}$
将误判为相等。
【NOI2013】向量内积的更多相关文章
- 【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 ...
- P1224 [NOI2013]向量内积
传送门 发现这个内积和矩乘有点像,考虑构造一个 $n$ 行 $m$ 列的矩阵 $A$,每一行都是一个题目给定的 $m$ 维向量 设 $B=AA^T$ ,其中 $A^T$ 为 $A$ 的转置矩阵,那么对 ...
- luogu P1224 [NOI2013]向量内积
传送门 挺有意思的一道题 暴力60就是枚举每个向量暴力check,随机选向量就能多骗一些分 然后两个向量内积要模\(k\)为\(0\),那么如果全部不为\(0\)就不合法.先考虑\(k=2\),对于向 ...
- 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 ...
- BZOJ3243 [Noi2013]向量内积 【乱搞】
题目链接 BZOJ3243 题解 模数只有\(2\)或\(3\),可以大力讨论 如果模数为\(2\),乘积结果只有\(1\)或\(0\) 如果一个向量和前面所有向量乘积都为\(1\),那么其和前面向量 ...
随机推荐
- PAT 1016 Phone Bills[转载]
1016 Phone Bills (25)(25 分)提问 A long-distance telephone company charges its customers by the followi ...
- 8款世界级Webmail工具推荐
Webmail软件或者基于Web的电子邮件包含两个重要方面:Webmail客户端和Webmail提供商.Webmail客户端负责通过本地或远程服务器使用POP3和SMTP协议发送和接收电子邮件.Web ...
- javascript脚本实现浏览器自动点击(阿里员工秒杀月饼)
原文地址https://blog.csdn.net/ani521smile/article/details/52575063 秒杀活动页面 <!DOCTYPE HTML> <html ...
- lnmp之mysql5.5.17安装
先执行命令yum install cmake mysql5.5采用的是cmake安装(更先进的configure) wget下载目录(到清华大学的镜像站下载) [root@localhost loca ...
- LR和SVM的相同和不同
之前一篇博客中介绍了Logistics Regression的理论原理:http://www.cnblogs.com/bentuwuying/p/6616680.html. 在大大小小的面试过程中,经 ...
- uva10003
/* 2014.3.6 这题说的是给你了一根木棒 然后 n 个点(线段上的点) 然后计算 在这 n个点上都切下去的 最小花费 举个例子 100 3 25 50 75 如果 从 25 开始切 然后切 5 ...
- 奋斗史-IT女生是怎样炼成的
IT女生的奋斗史 终于来到了毕业季,感觉有点伤感! 记得11年来到大学的时候,还是那么懵懂,什么都不懂,几乎连电脑的基本操作都不会!自己小时候虽然家里穷,但是从小就觉得“软件”是个很神奇的东西,很了不 ...
- python堆排序
堆是完全二叉树 子树是不相交的 度 节点拥有子树的个数 满二叉树: 每个节点上都有子节点(除了叶子节点) 完全二叉树: 叶子结点在倒数第一层和第二层,最下层的叶子结点集中在树的左部 ,在右边的话,左子 ...
- Linux服务器---配置apache支持用户认证
Apache支持用户认证 为了服务器的安全,通常用户在请求访问某个文件夹的时候,Apache可以要求用户输入有效的用户名和登录密码 1.创建一个测试目录 [root@localhost cgi-bin ...
- [转载]onclientclick和onclick区别
OnClientClick是客户端脚本,一般使用javascript,在客户端,也就是IE中运行,点击后马上执行OnClick是服务器端事件处理函数,使用C#或者vb.net,在服务器端,也就是IIS ...