洛谷P1224 向量内积
什么毒瘤......
题意:给定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中某个元素的式子化开,会有:
然后就做完了......
#include <cstdio>
#include <algorithm>
#include <ctime>
#include <iostream> const int N = ; int a[N][], now[N], C[N], D[N], E[N], MO, F[N];
int n, d; inline bool check(int i, int j) {
int ans = ;
for(int k = ; k <= d; k++) {
(ans += a[i][k] * a[j][k]) %= MO;
}
return ans;
} inline void solve1() {
int T = , f = -;
while((T--) && (f == -)) {
int Sum = ;
for(int i = ; i <= n; i++) {
C[i] = rand() & ;
Sum += C[i];
}
//mul(1, n, d, C, a, D);
for(int i = ; i <= d; i++) {
D[i] = ;
for(int j = ; j <= n; j++) {
D[i] += C[j] * a[j][i];
D[i] &= ;
}
}
//mul(1, d, n, D, aT, E);
for(int i = ; i <= n; i++) {
E[i] = ;
for(int j = ; j <= d; j++) {
E[i] += D[j] * a[i][j];
E[i] &= ;
}
}
//mul_one(1, n, n, C, F);
for(int i = ; i <= n; i++) {
F[i] = ((Sum - C[i]) + C[i] * now[i]) & ;
if(E[i] != F[i]) {
f = i;
break;
}
}
}
if(f == -) {
printf("%d %d\n", f, f);
return;
}
for(int i = ; i <= n; i++) {
if(i == f) {
continue;
}
if(!check(i, f)) {
printf("%d %d\n", std::min(i, f), std::max(i, f));
return;
}
}
return;
} inline void solve2() {
int T = , f = -;
while((T--) && (f == -)) {
int Sum = ;
for(int i = ; i <= n; i++) {
C[i] = rand() % MO;
Sum += C[i];
}
//mul(1, n, d, C, a, D);
for(int i = ; i <= d; i++) {
for(int ii = ; ii <= d; ii++) {
int pos = (i - ) * d + ii;
D[pos] = ;
for(int j = ; j <= n; j++) {
D[pos] += C[j] * a[j][i] * a[j][ii];
D[pos] %= MO;
}
}
}
//mul(1, d, n, D, aT, E);
for(int i = ; i <= n; i++) {
E[i] = ;
for(int j = ; j <= d; j++) {
for(int jj = ; jj <= d; jj++) {
int pos = (j - ) * d + jj;
E[i] += D[pos] * a[i][j] * a[i][jj];
E[i] %= MO;
}
}
}
//mul_one(1, n, n, C, F);
for(int i = ; i <= n; i++) {
F[i] = ((Sum - C[i]) + C[i] * now[i]) % MO;
if(E[i] != F[i]) {
f = i;
break;
}
}
}
if(f == -) {
printf("%d %d\n", f, f);
return;
}
for(int i = ; i <= n; i++) {
if(i == f) {
continue;
}
if(!check(i, f)) {
printf("%d %d\n", std::min(i, f), std::max(i, f));
break;
}
}
return;
} int main() {
srand(time());
int k, x;
scanf("%d%d%d", &n, &d, &k);
MO = k;
bool f = (k == );
for(int i = ; i <= n; i++) {
now[i] = ;
for(int j = ; j <= d; j++) {
scanf("%d", &x);
a[i][j] = x % k;
now[i] += a[i][j] * a[i][j];
}
now[i] %= k;
} f ? solve1() : solve2();
return ;
}
AC代码
题解里还有一种神奇的解法,使用了乘法分配率,每次把一个向量和它上面所有向量的乘积加起来跟(i-1) % MO判断。
分配一下,就是把上面向量的每一维都做前缀和,然后相乘。
这样做其实有一点问题,就是可能有乘积为0的检测不出来。不过上面那种方法也彼此彼此了。
洛谷P1224 向量内积的更多相关文章
- 洛谷 P1224 - [NOI2013] 向量内积(随机化)
洛谷题面传送门 一道很神的随机化. 首先由于我们要求向量点乘 \(\bmod k\) 的值,因此我们可以将所有 \(x_{i,j}\) 都模上 \(k\),显然该操作不影响结果正确性. 注意到这里的 ...
- 洛谷P2520向量
题目传送门 看到数据范围其实就可以确定这是一道结论题. 首先分析,给定你的向量的两个坐标a,b有八种组合方式可以用,但实际上整理一下可以得出实际上只有五种,x/y ±2a,x/y ±2b,x+a,y+ ...
- P1224 [NOI2013]向量内积
传送门 发现这个内积和矩乘有点像,考虑构造一个 $n$ 行 $m$ 列的矩阵 $A$,每一行都是一个题目给定的 $m$ 维向量 设 $B=AA^T$ ,其中 $A^T$ 为 $A$ 的转置矩阵,那么对 ...
- luogu P1224 [NOI2013]向量内积
传送门 挺有意思的一道题 暴力60就是枚举每个向量暴力check,随机选向量就能多骗一些分 然后两个向量内积要模\(k\)为\(0\),那么如果全部不为\(0\)就不合法.先考虑\(k=2\),对于向 ...
- [BZOJ]3243 向量内积(Noi2013)
小C做了之后很有感觉的题目之一,但因为姿势不对调了很久. Description 两个d 维向量A=[a1,a2,...,ad]与B=[b1,b2,...,bd]的内积为其相对应维度的权值的乘积和,即 ...
- 洛谷P3222 [HNOI2012]射箭(计算几何,半平面交,双端队列)
洛谷题目传送门 设抛物线方程为\(y=ax^2+bx(a<0,b>0)\),我们想要求出一组\(a,b\)使得它尽可能满足更多的要求.这个显然可以二分答案. 如何check当前的\(mid ...
- FFT/NTT总结+洛谷P3803 【模板】多项式乘法(FFT)(FFT/NTT)
前言 众所周知,这两个东西都是用来算多项式乘法的. 对于这种常人思维难以理解的东西,就少些理解,多背板子吧! 因此只总结一下思路和代码,什么概念和推式子就靠巨佬们吧 推荐自为风月马前卒巨佬的概念和定理 ...
- 「BZOJ1038」「洛谷P2600」「ZJOI2008」瞭望塔 半平面交+贪心
题目链接 BZOJ/洛谷 题目描述 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安. 我们将H村抽象为一维的轮廓.如下图所示: 我们可以用一条山的上方 ...
- 洛谷P4288||bzoj3564 [SHOI2014]信号增幅仪
bzoj3564 洛谷P4288 可以旋转一下坐标轴使得x轴与长轴方向对齐,然后将所有的横坐标变为自身除以放大倍数,然后就做一个最小圆覆盖 #include<cstdio> #includ ...
随机推荐
- bootstrap模态框动态赋值, ajax异步请求数据后给id为queryInfo的模态框赋值并弹出模态框(JS)
/查询单个 function query(id) { $.ajax({ url : "/small/productServlet", async : true, type : &q ...
- .Net MVC4 log4net的配置
一.首先在使用log4net记录日志的时候,我们要引用log4net.dll文件 二.在web.config中添加一下配置代码 <configSections> <!-- For m ...
- Programming好文解读系列(—)——代码整洁之道
注:初入职场,作为一个程序员,要融入项目组的编程风格,渐渐地觉得系统地研究下如何写出整洁而高效的代码还是很有必要的.与在学校时写代码的情况不同,实现某个功能是不难的,需要下功夫的地方在于如何做一些防御 ...
- @Param注解
关于mybatis的@Param注解和参数 引用 https://www.cnblogs.com/whisper527/p/6568028.html 薇飘意 1,使用@Param注解 当以下面的方式进 ...
- OSError: mysql_config not found
使用Python3开发一个管理平台,用MySQL数据库存放元数据.使用pip安装mysqlclient模块时出现“OSError: mysql_config not found”错误. 解决: # a ...
- TP5系统变量输出
1.超全局变量 模板中: {$Think.sever.server_name} //全部小写,输出blog.cn 控制器: $_SERVER['SERVER_NAME'] ...
- Calendar用法随笔
平时在处理时间问题的时候,一般会想到用java.util.Date类型,在使用倒时间的运算的时候,就不是很方便,找找到了java.util.Calendar类,中文意思是“日历”,以下就是自己对这个类 ...
- CS新建排版
1.拉菜单栏barmanage,去掉不要的头部和尾部 ,选择控件bar属性optionsbar 全部为false,防止菜单拖动. 2.拉一个panelcontrol属性dock 设置顶部,在拉一个p ...
- hdu-1421(dp)
解题思路:dp[i][j]表示前i个物品中取k对所要的最小花费: 首先得对物品进行处理,因为需要当前物品减前一个物品的平方和最小: 所以先排序,因为排序的相邻两个的差的平方一定最小: 然后转移方程:d ...
- .net core 2.0 Autofac
参考自 https://github.com/VictorTzeng/Zxw.Framework.NetCore 安装Autofac,在`project.csproj`加入 <PackageRe ...