2020牛客暑期多校训练营(第四场)I Investigating Legions
题意
I Investigating Legions
有N个点(30-300)和M(1~N/30)个团,每个点仅属于
一个团(等概率在0~M-1选择一个整数作为它的团)。
• 有一个常数 S(20~100)。按以下的方式生成 01 矩阵 a:
如果 i 和 j 属于同一个团,a[i][j]=1,否则a[i][j]=0。同时该
值有 1/S 的概率被翻转。
• 给出 N 和 S 和 a(M 不给出),要还原每个点属于的团。
题解
其实不是1/S,rand() can be considered as a uniform random function. i.e., select a integer from interval [0, \mathrm{lcm}(m, S)-1][0,lcm(m,S)−1] with equal probability.所以取个2就可以了。然后就暴力去找能连通超过m/2的点就可以了。读题啊,读题啊,读题啊,读题啊,读题啊,读题啊,读题啊。
代码
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
#define N 305
int f[N][N];
char arr[N * N];
int a[N];
int main() {
int t;
scanf("%d", &t);
while(t--) {
int n, s;
scanf("%d%d", &n, &s);
scanf("%s", arr);
int ct = 0;
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
f[i][j] = f[j][i] = arr[ct++] - '0';
}
f[i][i] = 1;
}
fill(a, a + n + 1, -1);
int id = 0;
for(int i = 0; i < n; i++) {
vector<int> v;
if(a[i] == -1) {
for(int j = 0; j < n; j++) {
if(f[i][j] && a[j] == -1) {
v.push_back(j);
}
}
int m = v.size();
for(int j = 0; j < n; j++) {
int num = 0;
for(auto k : v) {
if(f[k][j]) {
num++;
}
}
if(num >= m / 2) {
a[j] = id;
}
}
id++;
}
}
for(int i = 0; i < n - 1; i++) {
printf("%d ", a[i]);
}
printf("%d\n", a[n - 1]);
}
}