zoukankan      html  css  js  c++  java
  • 题解 向量内积

    题目传送门

    Description

    两个 (d) 维向量 (A=[a_1, a_2 ,...,a_d])(B=[b_1 ,b_2 ,...,b_d]) 的内积为其相对应维度的权值的乘积和,即:

    [(A,B) = displaystyle sum_{i=1}^d{a_ib_i} = a_1b_1 + a_2b_2 + ldots + a_db_d ]

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

    第一行包含 (3) 个正整数 (n,d,k),分别表示向量的个数、维数以及待检测的倍数。

    接下来 (n) 行每行有 (d) 个非负整数,其中第 (i) 行的第 (j) 个整数表示向量 ([x_i]) 的第 (j) 维权值 (x_{i,j})

    包含两个整数,用空格隔开。

    如果存在两个向量 (x_p,x_q) 的内积为 (k) 的整数倍,则输出两个向量的编号 (p)(q)(要求 (p<q))。如果存在多组这样的向量组合,输出其中任意一组即可。

    若不存在这样的向量组合,则输出两个 (-1)

    测试点编号 (n) (d) (k) (x_i)
    (1) (2) (20) (2) (le 10)
    (2) (5) (20) (2) (le 10)
    (3) (10) (20) (3) (le 10)
    (4) (20) (20) (2) (le 100)
    (5) (50) (20) (3) (le 100)
    (6) (50) (50) (2) (le 1000)
    (7) (50) (50) (3) (le 3000000)
    (8) (80) (80) (2) (le 2000000)
    (9) (100) (100) (3) (le 3000000)
    (10) (500) (100) (3) (le 3000000)
    (11) (1000) (100) (2) (le 2000000)
    (12) (1000) (100) (3) (le 3000000)
    (13) (10000) (100) (2) (< 10)
    (14) (10000) (100) (3) (< 10)
    (15) (15000) (100) (2) (< 10)
    (16) (18000) (100) (2) (< 10)
    (17) (20000) (100) (2) (< 10)
    (18) (50000) (30) (3) (< 10)
    (19) (80000) (30) (3) (< 10)
    (20) (100000) (30) (3) (< 10)

    Solution

    考虑到正经做法不是很好做,考虑不太正经的做法。

    首先可以发现 (kle 3),那么先考虑 (k=2) 时候的情况。可以发现,如果对于 (i) 存在:

    [sum_{j=1}^{i-1}|x_i·x_j| otequiv i-1 pmod 2 ]

    就说明一定存在一个解了。正确概率不是很会算。快速算的话,可以对向量做个前缀和。

    考虑 (k=3) ,你发现 (x^{k-1}equiv pmod k)(k) 为质数),所以如果对于 (i) 存在:

    [sum_{j=1}^{i-1}|x_i·x_j|^2 otequiv i-1pmod 2 ]

    那么也说明一定存在一个解了。这个也可以用前缀和算,复杂度 (Theta(nd^2))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define MAXN 100005
    #define MAXM 105
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
    
    int n,d,mod,s[MAXN][MAXM],ind[MAXN],s1[MAXM],s2[MAXM][MAXM];
    
    signed main(){
    //	freopen ("P1224_18.in","r",stdin);
    	srand (20050913); 
    	read (n,d,mod);
    	for (Int i = 1;i <= n;++ i) for (Int j = 1;j <= d;++ j) read (s[i][j]),s[i][j] %= mod;
    	for (Int i = 1;i <= n;++ i) ind[i] = i;
    	for (Int times = 1;times <= 1;++ times){
    		random_shuffle(ind + 1,ind + n + 1);
    		if (mod == 2){
    			memset (s1,0,sizeof (s1));
    			for (Int i = 1;i <= n;++ i){
    				int ans = 0;
    				for (Int j = 1;j <= d;++ j) ans ^= s[ind[i]][j] & s1[j],s1[j] ^= s[ind[i]][j];
    				if (ans == (i - 1) % mod) continue;
    				for (Int j = 1;j < i;++ j){
    					ans = 0;
    					for (Int k = 1;k <= d;++ k) ans ^= s[ind[i]][k] & s[ind[j]][k];
    					if (!ans){
    						write (min (ind[i],ind[j])),putchar (' '),write (max (ind[i],ind[j])),putchar ('
    ');
    						return 0;
    					}
    				}
    			}
    		}
    		else{
    			memset (s2,0,sizeof (s2));
    			for (Int i = 1;i <= n;++ i){
    //				cout << i << endl;
    				int ans = 0;
    				for (Int k1 = 1;k1 <= d;++ k1)
    					for (Int k2 = 1;k2 <= d;++ k2)
    						(ans += s[ind[i]][k1] * s[ind[i]][k2] * s2[k1][k2]),
    						(s2[k1][k2] += s[ind[i]][k1] * s[ind[i]][k2]);
    				ans %= mod;
    				if (ans == (i - 1) % mod) continue;
    				for (Int j = 1;j < i;++ j){
    					ans = 0;
    					for (Int k = 1;k <= d;++ k) (ans += s[ind[i]][k] * s[ind[j]][k] % mod) %= mod;
    					if (!ans){
    						write (min (ind[i],ind[j])),putchar (' '),write (max (ind[i],ind[j])),putchar ('
    ');
    						return 0;
    					}
    				}
    			}
    		}
    	}
    	puts ("-1 -1");
    	return 0;
    } 
    
  • 相关阅读:
    fixed固定定位实现可拖拽
    描述windows和linux如何抓取数据报文
    Javascript基础系列(七)-BOM
    Javascript基础系列(六)-函数
    Javascript基础系列(五)-面向对象
    浅述数组排序
    Android 相对布局 RelativeLayout
    Android 框架布局 FrameLayout
    Android 线性布局 计算器
    Android 线性布局 LinearLayout
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/15120464.html
Copyright © 2011-2022 走看看