小C做了之后很有感觉的题目之一,但因为姿势不对调了很久。

Description

  两个d 维向量A=[a1,a2,...,ad]与B=[b1,b2,...,bd]的内积为其相对应维度的权值的乘积和,即:

      

  现有 n 个d 维向量x1,...,xn ,小喵喵想知道是否存在两个向量的内积为k的倍数。请帮助她解决这个问题。

Input

  第一行包含3个正整数n,d,k,分别表示向量的个数,维数以及待检测的倍数。接下来n行每行有d个非负整数,其中第i行的第j个整数表示向量xi的第j维权值xi,j。

Output

  包含两个整数,用空格隔开。如果存在两个向量xp,xq的内积为k的整数倍,则输出两个向量的编号p与q(要求p<q)。如果存在多组这样的向量组合,输出其中任意一组即可。若不存在这样的向量组合,则输出两个-1。

Sample Input

  2 20 2
  0 0 1 1 1 1 1 0 1 1 1 0 1 0 0 0 1 1 1 1
  1 0 1 0 1 0 1 1 1 1 0 1 1 1 0 1 1 0 1 0

Sample Output

  1 2

Hint

  N<=100000,D<=30,K<=3,Xi,j<10。

  

Solution

  看见题目后基本能想到的要点:

    ①k似乎很小?k=2时答案只可能是0或1,k=3则是0、1和2?

    ②向量内积的求和式其实就是矩阵乘法的计算式,两个向量的内积可以看做是1*d和d*1的矩阵相乘。

  继续深入:

    ①可以将题目表示为n*d和d*n的矩阵相乘,得到的n*n的矩阵就是n个向量两两之间的内积,判断n*n矩阵内是否有等于0的元素即可;

    ②直接计算和判断明显复杂度爆表,我们考虑将计算和判断部分进行优化:

      当k=2时,n*n的矩阵只有一种情况不是我们想要的,那就是除了对角线上的元素,其他都为1——设这样的矩阵为D;

           设原来的两个矩阵分别为A、B,相乘得到矩阵C;

           这样我们只需判断C和D是否相等即可,我们当然不会直接判断,这里需要用到一个小技巧。

           我们考虑随机生成一个n*1的矩阵T来与C、D相乘,判断C*T和D*T是否相等即可。

           随机次数3~5次基本不会出错,这样我们便将判断成功降到了O(n)。

           至于计算部分,我们只要按A*(B*T)的顺序就可以O(nd)得到C*T;

           由于矩阵D是确定的,主对角线O(nd)计算,O(n)再推一遍可以得到D*T。

           剩下的事情就是找出不相等的一位x,相当于找到了答案的一半(x一定是答案),O(nd)找另一半即可。

      当k=3时,我们可以脑补一个2^2≡1(mod 3),于是考虑将矩阵C、D的每个元素平方(注意不是将矩阵平方!)。

           这样矩阵D的每个除了主对角线上的元素便都是1了,像k=2那样判断C和D是否相等即可。

           至于怎么计算矩阵C呢?我们发现

              

           所以可以将矩阵A和B分别扩展成n*(d^2)和(d^2)*n的矩阵;

           即将d维向量扩展成一个d^2维的向量,新向量每一维都是旧向量某两维的乘积。

           有了这些,步骤基本就和k=2时的情况一样了。

           时间复杂度:O(nd^2)

      你会发现一个细节,数据中有n=10000,d=100,k=3的情况,n*(d^2)的空间完全不够开。

      当然没有叫你真的开一个n*(d^2)的矩阵啊(坏笑)!你会发现涉及到矩阵乘法的操作只有在计算C*T的时候,也就是说只有4次,只要把k=3的那两次特殊抠出来处理即可,具体实现可以看小C的代码。

#include <cstdio>
#include <algorithm>
#include <cstdlib>
#define MN 100005
#define MM 105
using namespace std;
struct matrix{int **ar; int h,l;}a,b,r,h;
int g[MN],f[MM],mod,n,m,sum; inline int read()
{
int n=,f=;char c=getchar();
while (c<'' || c>'') {if(c=='-')f=-; c=getchar();}
while (c>='' && c<='') {n=n*+c-''; c=getchar();}
return n*f;
} matrix newmatr(int n,int m)
{
matrix a;
a.h=n; a.l=m;
a.ar=new int*[n];
for (register int i=;i<n;++i) a.ar[i]=new int[m];
return a;
} matrix operator*(const matrix& a,const matrix& b)
{
matrix c=newmatr(a.h,b.l);
register int i,j,k;
for (i=;i<c.h;++i)
for (j=;j<c.l;c.ar[i][j++]%=mod)
for (c.ar[i][j]=,k=;k<a.l;++k) c.ar[i][j]+=a.ar[i][k]*b.ar[k][j];
return c;
} matrix operator&(const matrix& a,const matrix& b)
{
matrix c=newmatr(a.h,b.l);
register int i,j,kl,kr;
for (i=;i<c.h;++i)
for (j=;j<c.l;c.ar[i][j++]%=mod)
for (c.ar[i][j]=,kl=;kl<a.l;++kl)
for (kr=;kr<a.l;++kr) c.ar[i][j]+=a.ar[i][kl]*a.ar[i][kr]*b.ar[kl*a.l+kr][j];
return c;
} matrix operator|(const matrix& a,const matrix& b)
{
matrix c=newmatr(a.h*a.h,b.l);
register int i,j,k;
for (i=;i<c.h;++i)
{
register int x=i/a.h,y=i%a.h;
for (j=;j<c.l;c.ar[i][j++]%=mod)
for (c.ar[i][j]=,k=;k<a.l;++k) c.ar[i][j]+=a.ar[x][k]*a.ar[y][k]*b.ar[k][j];
}
return c;
} matrix ranmat(int n,int m)
{
matrix a=newmatr(n,m);
register int i,j;
for (i=;i<n;++i)
for (j=;j<m;++j) a.ar[i][j]=rand()%mod;
return a;
} int main()
{
srand();
register int i,j,k,o;
n=read(); m=read(); mod=read();
a=newmatr(n,m); b=newmatr(m,n);
for (i=;i<n;++i)
for (j=;j<m;++j) a.ar[i][j]=b.ar[j][i]=read()%mod;
for (i=;i<n;g[i++]%=mod)
for (j=;j<m;++j) g[i]+=a.ar[i][j]*a.ar[i][j];
if (mod==)
{
for (o=;o<=;++o)
{
r=ranmat(n,);
h=a*(b*r);
for (i=sum=;i<n;++i) sum^=r.ar[i][];
for (i=;i<n;++i) if (h.ar[i][]!=(sum^(r.ar[i][]&&!g[i]))) break;
if (i<n) break;
}
}
else if (mod==)
{
for (i=;i<n;++i) g[i]=g[i]*g[i]%mod;
for (o=;o<=;++o)
{
r=ranmat(n,);
h=a&(b|r);
for (i=sum=;i<n;++i) sum+=r.ar[i][];
for (i=;i<n;++i) if (h.ar[i][]!=(sum-(-g[i])*r.ar[i][])%mod) break;
if (i<n) break;
}
}
if (o>) return *printf("-1 -1");
for (j=;j<n;++j)
{
if (i==j) continue;
for (sum=k=;k<m;++k) sum+=a.ar[i][k]*a.ar[j][k];
if (!(sum%mod)) return *printf("%d %d",min(i+,j+),max(i+,j+));
}
}

Last Word

  反正依着小C这属性(才不是抖M),能让他发博客吐槽的题目大概又是什么虐了他千百遍的丧题吧。(其实是因为小C智障老是打挂题)

  一开始非常智障地跑去建n*(d^2)的矩阵,然后,然后就有了以上一段画风崩坏的代码……

  由于用了结构体矩阵来计算,代码似乎跑得出奇地慢,洛谷和BZOJ上都过了,自家的OJ(未开O2)死活过不去……

  所以不建议读者按矩阵计算,直接开数组即可,还有n*1的矩阵只要开成一维矩阵即可,这样代码效率可以有巨大的提升。

  小C的代码效率较慢的锅都是因为开了二维数组,似乎 new 和 return结构体 在这道题效率还行?

  总之,小C觉得这还算是一道挺有想法的题啦。其主要思想就是利用矩阵乘法的结合律来改变计算顺序以降低时间复杂度,还有就是在判断两个矩阵是否相等时用了一些小技巧,至于2^2≡1(mod 3)什么的就是脑洞问题了吧!(QAQ觉得脑洞平了)

[BZOJ]3243 向量内积(Noi2013)的更多相关文章

  1. BZOJ 3243 向量内积

    Description 两个\(d\)维向量\(A=[a_{1},a_{2},...,a_{d}]\)与\(B=[b_{1},b_{2},...,b_{d}]\)的内积为其相对应维度的权值的乘积和,即 ...

  2. 【BZOJ3243】【NOI2013】向量内积(矩阵,数论)

    [BZOJ3243][NOI2013]向量内积(矩阵,数论) 题面 BZOJ 题解 这题好神仙. 首先\(60\)分直接是送的.加点随机之类的可以多得点分. 考虑正解. 我们先考虑一下暴力. 我们把\ ...

  3. [Noi2013]向量内积

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

  4. LOJ 2664. 「NOI2013」向量内积 解题报告

    #2664. 「NOI2013」向量内积 两个 \(d\) 维向量 \(A=[a_1, a_2 ,...,a_d]\) 与 \(B=[b_1 ,b_2 ,...,b_d]\) 的内积为其相对应维度的权 ...

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

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

  6. P1224 [NOI2013]向量内积

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

  7. luogu P1224 [NOI2013]向量内积

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

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

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

  9. 3243: [Noi2013]向量内积 - BZOJ

    Description 两个d 维向量A=[a1,a2,...,ad]与B=[b1,b2,...,bd]的内积为其相对应维度的权值的乘积和,即: 现有 n 个d 维向量x1,...,xn ,小喵喵想知 ...

随机推荐

  1. labview与单片机串口通信

    labview与单片机串口通信   VISA是虚拟仪器软件体系结构的缩写(即Virtual Instruments Software Architecture),实质上是一个I/O口软件库及其规范的总 ...

  2. js 点击 返回顶部 动画

    附上效果图 触发前 触发后 HTML代码: CSS代码 JS代码 由于复制文本太丑了 所以直接放的图片  但是我在评论区把js代码又复制了一边 以便你们使用

  3. Connect Appium Server Fail.A new session could not be created

    1.由于安卓测试机性能低下,并不能支持测试工作,想安装一个模拟器帮助测试,然后发现群里有朋友发了一个夜神模拟器..下载..安装..美滋滋的准备运行脚本.What..居然报错了..orz..然后百度查找 ...

  4. Spring Cache扩展:注解失效时间+主动刷新缓存(二)

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  5. tomcat-theory

    (一) java类:applet,servlet,jsp JSP:.jsp-->.java-->(JVM).classJDK:javac,.java-->.classweb:Serv ...

  6. dubbo debug过程中一个有趣的问题

    最近在debug dubbo代码过程中遇到的很有趣的问题 我们都知道dubbo ReferenceBean是消费者的spring bean包装,为了查一个consumer端的问题,在Reference ...

  7. 由路由器AP隔离引起的WEB服务不能访问的问题

    最近在自己的电脑上运行了一个Web服务,发现它只能被本机访问,无法在同一个局域网的其它设备访问. 于是在网上搜索了各种资料,通通都是在操作系统层面来分析解决问题的. 而我怎么尝试都不成功的情况下,差点 ...

  8. spring4——IOC之基于注解的依赖注入(DI )

    spring容器对于Bean的创建和对象属性的依赖注入提供了注解的支持,让我们在开发中能够更加便捷的实现对象的创建和对象属性的依赖注入.一,对于Bean的创建spring容器提供了以下四个注解的支持: ...

  9. 【iOS】UIViewController基类的实现

    继承是面向对象编程语言的三大特性之一,写好基类会给App的开发带来极大的方便.在iOS开发中,一般一个页面就对应一个ViewController,ViewController在开发中用的也很多,写一个 ...

  10. yum 安装Apache

    1.查看是否安装Apache,命令:  rpm    -qa    httpd 2.yum install httpd ,yum安装Apache 3.chkconfig    httpd  on  s ...