[NOI2013] 向量內積
題目描述
兩個 \(d\) 維向量 \(A=[a_1,a_2,\ldots,a_d]\) 與 \(B=[b_1,b_2,\ldots,b_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\)。
樣例輸入 #1
3 5 2
1 0 1 0 1
1 1 0 1 0
0 1 0 1 1
樣例輸出 #1
2 3
AC
觀察資料範圍,發現\(k=2或k=3\),可以分兩類
\(k=2\)
取模後結果為\(1\)或\(0\),可以求每個向量與前面向量的和的內積,如果這個向量與前面的向量不符合題目要求那麼結果必然是\(1\),所以和必然是\((i-1) mod k\)
\(k=3\)
取模後結果是0,1,2,但是平方後再取模結果就是0,1。與\(k=2\)相同
#include<bits/stdc++.h>
using namespace std;
inline int readn()
{
int x=0,f=1;
char ch;
while(ch<48||ch>57)
{
ch=getchar();
if(ch==45)f=-1;
}
while(ch>=48&&ch<=57)
{
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*f;
}
vector<signed> a[100005];
signed n,k,d;
signed k2[150];
signed k3[150][150];
signed solve(int x)
{
int ans=0;
if(k==2) for(register int i=0;i<d;i++)
{
ans^=a[x][i]&k2[i];
k2[i]^=a[x][i];
}
else for(register int i=0;i<d;i++)
for(register int j=0;j<d;j++)
{
ans+=a[x][i]*a[x][j]*k3[i][j]%k;
k3[i][j]+=a[x][i]*a[x][j];
}
return ans%k;
}
signed main()
{
n=readn();
d=readn();
k=readn();
for(register int i=1;i<=n;i++)
{
for(register int j=1;j<=d;j++)
{
a[i].push_back(readn()%k);
}
}
int ans;
for(register int i=1;i<=n;i++)
if(solve(i)!=(i-1)%k)
for(register int l=1;l<i;l++)
{
ans=0;
for(register int p=0;p<d;p++)ans+=a[l][p]*a[i][p];
if(ans%k==0)
{
printf("%d %d",l,i);
return 0;
}
}
printf("-1 -1");
return 0;
}
Collective Mindsets(hard)
題目描述
一共有 \(n\) 個殭屍,每個殭屍頭上有一個 \(1 \sim n\) 之間的數字(可重複!),每個殭屍只能看到其他 \(n - 1\) 個殭屍頭頂的數字,當然,他們也知道自己的編號。 要求提供一種策略,使所有殭屍只利用自己知道的資訊同時猜自己頭頂的數字,保證至少有一個殭屍猜對。
輸入格式
第一行,一個正整數 \(T\),表示資料組數。
接下來對於每組資料,第一行包含兩個正整數 \(n\) 和 \(r\),表示殭屍總數與當前殭屍的編號,下一行包括 \(n-1\) 個正整數,表示當前殭屍看到的所有其他殭屍頭頂的編號是多少(按殭屍編號升序排列)。
輸出格式
對於每組資料輸出一行一個整數,表示該殭屍的猜測。
資料範圍
\(1 \le T \le 50000\),\(2 \le n \le 6\),\(1 \le r \le n\)。
樣例輸入 #1
4
2 1
1
2 2
1
2 1
2
2 2
2
樣例輸出 #1
1
2
2
1
樣例輸入 #2
2
5 2
2 2 2 2
6 4
3 2 6 1 2
樣例輸出 #2
5
2
做法
總共有n個殭屍,頭上只有n個號碼,無論哪種方法,猜中的機率都是一定的,所以應該不重複的把所有情況猜一遍所以可以設除第\(R\)個人的數之和為\(sum\),讓這個猜\((sum+r)mod n\)每個人都如此,就不會有重複的情況
#include<iostream>
using namespace std;
int n,r,x,ans;
int T;
int j;
int main()
{
cin>>T;
while(T--)
{
ans=0;
cin>>n>>r;
for(int i=1;i<n;i++)
{
cin>>x;
ans+=x;
}
j=0;
while((j+ans)%n!=r%n)j++;
cout<<j+1<<endl;
}
return 0;
}