什么毒瘤......

题意:给定n个d维向量,定义向量a和b的内积为

求是否存在两个向量使得它们的内积为k的倍数,并给出任一种方案。k <= 3。

解:很容易想到一个暴力是n2d的。显然我们不能n2枚举,所以要一次性把一个向量跟多个向量判断。

先思考k = 2的情况,显然每个位置和内积非0即1,这启发我们使用二进制。

假如把一个内积看成一个B进制数或者一个多项式,变量是B,我们就能发现,如果两个向量的内积为x,那么这个多项式的值也是x。

这种情况只要B取一个奇数就行了。理由是内积每一项非0即1,而进制为奇数的话,每一项的xi % 2 = 1,奇偶性不变。所以最后加起来和直接加起来的奇偶性相同。

k = 3的时候只要进制为3a + 1就行了。所以最终我们选择7进制。

然后有个很严峻的问题:我们要找一个运算使之与按位乘相对应。先想到了转成指标加法,经过一番推倒之后发现不可行。然后陷入江局......

正解:再观察一波内积式子,您就会发现这个其实是矩阵乘法中的一个位置的计算式......反正我是没发现。

那么令A = n × d的矩阵,B = A * AT,则Bi,j就是i和j的内积。

然后我们只需检验B和全1矩阵(对角线不一定是1)是否相同即可。这有一个经典算法:随机向量法。

随机出来的向量哪一位不同,就表明在全1矩阵的哪一列中存在差异。枚举跟这个向量匹配的向量即可。

k = 3的时候,我们把B中每一个元素都取平方,这样1和2都会变成1。

那么怎么把B中的每个元素取平方呢?

把B中某个元素的式子化开,会有:

然后就做完了......

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <ctime>
  4. #include <iostream>
  5.  
  6. const int N = ;
  7.  
  8. int a[N][], now[N], C[N], D[N], E[N], MO, F[N];
  9. int n, d;
  10.  
  11. inline bool check(int i, int j) {
  12. int ans = ;
  13. for(int k = ; k <= d; k++) {
  14. (ans += a[i][k] * a[j][k]) %= MO;
  15. }
  16. return ans;
  17. }
  18.  
  19. inline void solve1() {
  20. int T = , f = -;
  21. while((T--) && (f == -)) {
  22. int Sum = ;
  23. for(int i = ; i <= n; i++) {
  24. C[i] = rand() & ;
  25. Sum += C[i];
  26. }
  27. //mul(1, n, d, C, a, D);
  28. for(int i = ; i <= d; i++) {
  29. D[i] = ;
  30. for(int j = ; j <= n; j++) {
  31. D[i] += C[j] * a[j][i];
  32. D[i] &= ;
  33. }
  34. }
  35. //mul(1, d, n, D, aT, E);
  36. for(int i = ; i <= n; i++) {
  37. E[i] = ;
  38. for(int j = ; j <= d; j++) {
  39. E[i] += D[j] * a[i][j];
  40. E[i] &= ;
  41. }
  42. }
  43. //mul_one(1, n, n, C, F);
  44. for(int i = ; i <= n; i++) {
  45. F[i] = ((Sum - C[i]) + C[i] * now[i]) & ;
  46. if(E[i] != F[i]) {
  47. f = i;
  48. break;
  49. }
  50. }
  51. }
  52. if(f == -) {
  53. printf("%d %d\n", f, f);
  54. return;
  55. }
  56. for(int i = ; i <= n; i++) {
  57. if(i == f) {
  58. continue;
  59. }
  60. if(!check(i, f)) {
  61. printf("%d %d\n", std::min(i, f), std::max(i, f));
  62. return;
  63. }
  64. }
  65. return;
  66. }
  67.  
  68. inline void solve2() {
  69. int T = , f = -;
  70. while((T--) && (f == -)) {
  71. int Sum = ;
  72. for(int i = ; i <= n; i++) {
  73. C[i] = rand() % MO;
  74. Sum += C[i];
  75. }
  76. //mul(1, n, d, C, a, D);
  77. for(int i = ; i <= d; i++) {
  78. for(int ii = ; ii <= d; ii++) {
  79. int pos = (i - ) * d + ii;
  80. D[pos] = ;
  81. for(int j = ; j <= n; j++) {
  82. D[pos] += C[j] * a[j][i] * a[j][ii];
  83. D[pos] %= MO;
  84. }
  85. }
  86. }
  87. //mul(1, d, n, D, aT, E);
  88. for(int i = ; i <= n; i++) {
  89. E[i] = ;
  90. for(int j = ; j <= d; j++) {
  91. for(int jj = ; jj <= d; jj++) {
  92. int pos = (j - ) * d + jj;
  93. E[i] += D[pos] * a[i][j] * a[i][jj];
  94. E[i] %= MO;
  95. }
  96. }
  97. }
  98. //mul_one(1, n, n, C, F);
  99. for(int i = ; i <= n; i++) {
  100. F[i] = ((Sum - C[i]) + C[i] * now[i]) % MO;
  101. if(E[i] != F[i]) {
  102. f = i;
  103. break;
  104. }
  105. }
  106. }
  107. if(f == -) {
  108. printf("%d %d\n", f, f);
  109. return;
  110. }
  111. for(int i = ; i <= n; i++) {
  112. if(i == f) {
  113. continue;
  114. }
  115. if(!check(i, f)) {
  116. printf("%d %d\n", std::min(i, f), std::max(i, f));
  117. break;
  118. }
  119. }
  120. return;
  121. }
  122.  
  123. int main() {
  124. srand(time());
  125. int k, x;
  126. scanf("%d%d%d", &n, &d, &k);
  127. MO = k;
  128. bool f = (k == );
  129. for(int i = ; i <= n; i++) {
  130. now[i] = ;
  131. for(int j = ; j <= d; j++) {
  132. scanf("%d", &x);
  133. a[i][j] = x % k;
  134. now[i] += a[i][j] * a[i][j];
  135. }
  136. now[i] %= k;
  137. }
  138.  
  139. f ? solve1() : solve2();
  140. return ;
  141. }

AC代码

题解里还有一种神奇的解法,使用了乘法分配率,每次把一个向量和它上面所有向量的乘积加起来跟(i-1) % MO判断。

分配一下,就是把上面向量的每一维都做前缀和,然后相乘。

这样做其实有一点问题,就是可能有乘积为0的检测不出来。不过上面那种方法也彼此彼此了。

洛谷P1224 向量内积的更多相关文章

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

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

  2. 洛谷P2520向量

    题目传送门 看到数据范围其实就可以确定这是一道结论题. 首先分析,给定你的向量的两个坐标a,b有八种组合方式可以用,但实际上整理一下可以得出实际上只有五种,x/y ±2a,x/y ±2b,x+a,y+ ...

  3. P1224 [NOI2013]向量内积

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

  4. luogu P1224 [NOI2013]向量内积

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

  5. [BZOJ]3243 向量内积(Noi2013)

    小C做了之后很有感觉的题目之一,但因为姿势不对调了很久. Description 两个d 维向量A=[a1,a2,...,ad]与B=[b1,b2,...,bd]的内积为其相对应维度的权值的乘积和,即 ...

  6. 洛谷P3222 [HNOI2012]射箭(计算几何,半平面交,双端队列)

    洛谷题目传送门 设抛物线方程为\(y=ax^2+bx(a<0,b>0)\),我们想要求出一组\(a,b\)使得它尽可能满足更多的要求.这个显然可以二分答案. 如何check当前的\(mid ...

  7. FFT/NTT总结+洛谷P3803 【模板】多项式乘法(FFT)(FFT/NTT)

    前言 众所周知,这两个东西都是用来算多项式乘法的. 对于这种常人思维难以理解的东西,就少些理解,多背板子吧! 因此只总结一下思路和代码,什么概念和推式子就靠巨佬们吧 推荐自为风月马前卒巨佬的概念和定理 ...

  8. 「BZOJ1038」「洛谷P2600」「ZJOI2008」瞭望塔 半平面交+贪心

    题目链接 BZOJ/洛谷 题目描述 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安. 我们将H村抽象为一维的轮廓.如下图所示: 我们可以用一条山的上方 ...

  9. 洛谷P4288||bzoj3564 [SHOI2014]信号增幅仪

    bzoj3564 洛谷P4288 可以旋转一下坐标轴使得x轴与长轴方向对齐,然后将所有的横坐标变为自身除以放大倍数,然后就做一个最小圆覆盖 #include<cstdio> #includ ...

随机推荐

  1. 将选中项的value值赋给select的title

    $('select').change(function () { $(this).attr("title",$(this).find("option:selected&q ...

  2. linux pstree命令

    pstree命令可以使进程以tree的形式显示 pstree -ssystemd─┬─UVPHostd───6*[{UVPHostd}] ├─acpid ├─2*[agetty] ├─crond ├─ ...

  3. 一个实际的案例介绍Spring Boot + Vue 前后端分离

    介绍 最近在工作中做个新项目,后端选用Spring Boot,前端选用Vue技术.众所周知现在开发都是前后端分离,本文就将介绍一种前后端分离方式. 常规的开发方式 采用Spring Boot 开发项目 ...

  4. SpringBoot Junit Maven JaCoCo

    写一下最近写单体测试的一些笔记. SrpingBoot的测试用例: @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = ...

  5. win10 新建文件夹没有了

    1运行-regedit 2 在打开的注册表编辑器窗口,展开HKEY_CLASSES_ROOT,在HKEY_CLASSES_ROOT展开项中找到:Directory,再依次展开:Directory\Ba ...

  6. 七、.net core下配置、数据库访问等操作实现

    配置读取 .net core下读取配置还是有点麻烦的,本身没有System.Configuration.dll,所以在进行配置前需要自行引用Microsoft.Extensions.Configura ...

  7. React 学习(一) ---- React Element /组件/JSX

    学习React的时候,你可能听到最多的就是要先学习webpack, babel,要先学会配置然后才能学react 等等,一堆的配置就把我们吓着了,根本就没有心情就学习react了.其实在最开始学习re ...

  8. WMS工作原理

    图1:创建窗口 图2:通信过程 我们知道其实任何一个窗口的创建,最终都是会创建一个 ViewRootImpl对象.ViewRootImpl 是一很重要的类,类似 ActivityThread 负责跟A ...

  9. linux拷贝多个目录下的文件到同一个目录

    拷贝a目录下的a.txt和b目录下的b.txt到c目录 cp -a \ /root/a/a.txt \ /root/b/b.txt \ /root/c/

  10. IntelliJ IDEA 导航的 20 大特性

    本文由 ImportNew - elviskang 翻译自 dzone.欢迎加入翻译小组.转载请见文末要求. 在前面的文章里,我介绍了IntelliJ IDEA(以下称IntelliJ)中与代码补全及 ...