zoukankan      html  css  js  c++  java
  • [NOI2013] 向量内积

    一、题目

    点此看题

    二、解法

    发现本题 (k) 只有 (2,3) 两种取值,我们先考虑 (k=2) 的时候怎么做。

    可以固定 (x_i),去找有没有 (x_j) 合法。但是题目是不接受 (O(n^2d)) 判断的,可以考虑一些必要的判据,比如我们对 (jin[1,i)) 求出一个前缀和向量,然后和 (x_i) 点积。考虑如果全 (1) 的话点积的结果是 ((i-1)\% 2),那么如果不满足这个条件说明一定有一对 ((i,j)) 满足 (x_i,x_j) 的点积为 (0)

    这个判据是不充分的,所以我们把原序列 ( t random\_shuffle) 一下可以提高正确率。

    考虑 (k=3) 的时候怎么做,还是要搞出一个对于前缀而言的必要判据,但是因为此时出现了 (2),我们无法通过不全是某个数来推出存在某个数。考虑到 (2^2\%3=1),那么我们维护点积平方的前缀和,就可以类似 (k=2) 的方法做了。

    维护点积平方前缀和的方法就是考虑把平方拆开:

    [(sum a_ib_i)^2=sum_{i}sum_{j}a_ib_icdot a_jb_j=sum_isum_j(a_ia_j)cdot(b_ib_j) ]

    那么我们维护 (b_{i,j}) 表示第 (i) 位和第 (j) 位相乘的前缀和就可以快速计算了,时间复杂度 (O(nd^2))

    三、总结

    找到一组合法解可以先看某个范围内存不存在解,再去这个范围里找,至于判断某范围是否存在解可以用一些正确率较高的必要判据,再加之随机化就很难被卡掉。

    所有优于存在,注意它们之间的转化,本题判断不全为 (1) 优于判断存在 (0)

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int M = 100005;
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,d,k,id[M],a[M][105],b[105][105];
    int cal(int x,int y)
    {
    	int r=0;
    	for(int i=1;i<=d;i++)
    		r+=a[x][i]*a[y][i];
    	return r;
    }
    int check(int x)
    {
    	int r=0;
    	for(int i=1;i<=d;i++)
    		for(int j=1;j<=d;j++)
    		{
    			r+=b[i][j]*a[x][i]*a[x][j];
    			b[i][j]+=a[x][i]*a[x][j];
    		}
    	return r%k;
    }
    signed main()
    {
    	n=read();d=read();k=read();
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=d;j++)
    			a[i][j]=read()%k;
    	for(int t=1;t<=10;t++)
    	{
    		memset(b,0,sizeof b);
    		for(int i=1;i<=n;i++) id[i]=i;
    		random_shuffle(id+1,id+1+n);
    		for(int i=1;i<=n;i++)
    			if(check(id[i])!=(i-1)%k)
    			{
    				for(int j=1;j<i;j++)
    					if(cal(id[i],id[j])%k==0)
    					{
    						if(id[i]>id[j]) swap(i,j);
    						printf("%d %d
    ",id[i],id[j]);
    						return 0;
    					}
    			}
    	}
    	puts("-1 -1");
    }
    
  • 相关阅读:
    从一个表中查数据,插入另一个表
    sql 字段字符串内容替换
    安装VS2010后,如何设置老版本的项目文件不是默认用VS2010打开
    题解 [JOI 2019 Final] 独特的城市
    题解 [JOI 2019 Final] 硬币收藏
    题解 [CF720A] Closing ceremony
    [学习笔记] Miller-Rabin 质数测试
    题解 [CF332C] Students' Revenge
    题解 [CF525D] Arthur and Walls
    SpringMVC-拦截器
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/15033929.html
Copyright © 2011-2022 走看看