• 【洛谷1224】[NOI2013] 向量内积(随机+构造)


    点此看题面

    • 给定(n)(d)维向量,要求找出一对向量满足它们的内积是(k)的倍数。
    • (nle10^5,dle30)(nle2 imes10^4,dle100)(k=2)(3)

    前缀共同判定

    (k=2)为例,如果前(i-1)个向量与(i)的内积模(2)都不为(0)(只能为(1)),那么内积之和模(2)应该与(i-1)同余。

    内积的运算是满足分配律的,所以如果前(i-1)个向量的和向量与(i)的内积与(i-1)(2)不同余,则前(i-1)个向量中必然存在至少一个与(i)的内积模(2)(0),在确定一个向量的情况下直接去暴力找一趟即可。

    当然上述做法存在缺陷,尽管模(2)同余也不一定不存在,因此我们要对给定的向量(random\_shuffle),以防良心出题人的“良心数据”。

    (k=3)有些不太一样,因为模(3)余数不定,也就很难类似判定。

    但发现(1^2equiv2^2equiv1(mod 3)),所以我们只要求出前(i-1)个向量与(i)的内积的平方和与(i-1)(3)是否同余即可。

    平方直接大力拆开:((sum_{x=1}^da_{i,x}a_{j,x})^2=sum_{x=1}^dsum_{y=1}^da_{i,x}a_{i,y}a_{j,x}a_{j,y})。因此对每种(a_{j,x}a_{j,y})做个前缀和即可。

    代码:(O(nd^2))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define M 100
    using namespace std;
    int n,d,k,id[N+5],a[N+5][M+5],s[M+5],ss[M+5][M+5];
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	char oc,FI[FS],*FA=FI,*FB=FI;
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    }using namespace FastIO;
    int main()
    {
    	RI i,j,p,q,t;for(read(n,d,k),i=1;i<=n;++i) for(id[i]=i,j=1;j<=d;++j) read(a[i][j]),a[i][j]%=k;
    	srand(71717171);W(random_shuffle(id+1,id+n+1),true)//random_shuffle
    	{
    		if(k==2) for(i=1;i<=n;++i)//如果k=2
    		{
    			for(t=0,p=1;p<=d;++p) t^=a[id[i]][p]&s[p],s[p]^=a[id[i]][p];//统计前i-1个向量与第i个向量内积和
    			if(t==((i-1)&1)) continue;//如果同余不一定存在
    			for(j=1;j^i;++j) {for(t=0,p=1;p<=d;++p) t^=a[id[i]][p]&a[id[j]][p];if(!t) break;}//暴力找
    			return printf("%d %d
    ",min(id[i],id[j]),max(id[i],id[j])),0;//注意尽管有SPJ,但题面要求必须满足p<q
    		}
    		else for(i=1;i<=n;++i)//如果k=3
    		{
    			for(t=0,p=1;p<=d;++p) for(q=1;q<=d;++q)
    				t+=a[id[i]][p]*a[id[i]][q]*ss[p][q],(ss[p][q]+=a[id[i]][p]*a[id[i]][q])%=3;//统计前i-1个向量与第i个向量内积平方和
    			if(t%3==(i-1)%3) continue;//如果同余不一定存在
    			for(j=1;j^i;++j) {for(t=0,p=1;p<=d;++p) t+=a[id[i]][p]*a[id[j]][p];if(!(t%3)) break;}//暴力找
    			return printf("%d %d
    ",min(id[i],id[j]),max(id[i],id[j])),0;
    		}
    	}return 0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    delphi string 到excel
    VS 快捷键
    delphi Tform 释放
    cxSplitter 收缩和展开
    delphi 加载inc文件
    delphi TcxPageControl 动态嵌入窗体
    修改tomcat-users.xml 失效的问题
    TCXGRID 属性解释
    suse 设置ftp服务器
    用正则表达式修改html字符串的所有div的style样式
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu1224.html
Copyright © 2020-2023  润新知