2020牛客暑期多校训练营(第四场)I

链接:https://ac.nowcoder.com/acm/contest/5669/I
来源:牛客网

题意:每个样例中,n个数字,m个团,S是个概率,
这n个数字均属于且唯一属于m个团中的一个(be数组),a[i][j]代表i与j是否属于同一个团(1是0否),
对于每一个a[i][j],有1/S的概率将值修改(1变成0,0变成1).
现在给你n,S与二维数组a,求最可能的be数组,按照字典序输出.

给了这么个数据生成器,
2020牛客暑期多校训练营(第四场)I_第1张图片
数据范围:30≤n≤300,20≤S≤100 ,
给你数据的方式是
(0,1),(0,2)…(0,n-1),(1,2) … (n-3,n-1),(n-2,n-1)(0,1),(0,2)…(0,n−1),(1,2)…(n−3,n−1),(n−2,n−1).顺序
的01串

思路:s>=20,这就说明被修改的边会很少,那么我们先遍历一边数组,对每个还没有标记为某个团的人,先将所有人的权值初始化为0,将他与和他有边的所有人都压入一个数组中,对数组中的每个人,将所有与这个人相连的人的权值+1,将权值大的数字计为同一个团.

比如i还没有标记为某个团,记录所有和i有边的j为一个数组 [ j0,j1,j2…,n ] (i也要加入),对所有k满足 a[j][k]==1 将k的权值++(存在多个j则权值重复计算),当k的权值过了一个阀值,则将其加入i所在的团.

这个做法的依据是s很大,那么若一个数字s与i并不在同一个团,s与i所在团的点的边就会很少,这种操作计算出来的权值会呈现两级化的状态.

那么阀值取多少合适呢?
这是一个玄学的东西(我不会算),比赛时是用2/5*最大权值过的,结束后发现有些人用的是与i相连的边的一半,结束后我测试了一下 (4000/10000~4999/10000)*最大权值 范围内都可以,不知道是怎么算出来的,而且ac的代码中和s没啥关系,哪位概率大神能有证明的方法欢迎在评论区贴出来.

队友代码(FFFF就是那个阀值):

#define FFFF *4000/10000
#pragma comment(linker, "/STACK:102400000,102400000")
//#include
#include 
#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define fi first
#define se second
#define endl '\n'
#define o2(x) (x) * (x)
#define BASE_MAX 31
#define mk make_pair
#define eb emplace_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define clr(a, b) memset((a), (b), sizeof((a)))
#define iis                           \
    std::ios::sync_with_stdio(false); \
    cin.tie(0)
#define my_unique(x) sort(all(x)), x.erase(unique(all(x)), x.end())
using namespace std;
#pragma optimize("-O3")
typedef long long int64;
typedef unsigned long long uint64;
typedef pair pii;
// mt19937 rng(time(NULL));
// mt19937_64 rng64(chrono::steady_clock::now().time_since_epoch().count());
// mt19937_64 generator(std::clock());
// shuffle(arr, arr + n, generator);
inline int64 read() {
    int64 x = 0;
    int f = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') f |= (ch == '-'), ch = getchar();
    while (ch >= '0' && ch <= '9')
        x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x = f ? -x : x;
}
inline void write(int64 x, bool f) {
    if (x == 0) {
        putchar('0');
        if (f) putchar('\n');
        return;
    }
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    static char s[23];
    int l = 0;
    while (x != 0) s[l++] = x % 10 + 48, x /= 10;
    while (l) putchar(s[--l]);
    if (f) putchar('\n');
}
int lowbit(int x) { return x & (-x); }
template 
T big(const T &a1, const T &a2) {
    return a1 > a2 ? a1 : a2;
}
template 
T sml(const T &a1, const T &a2) {
    return a1 < a2 ? a1 : a2;
}
template 
T big(const T &f, const R &... r) {
    return big(f, big(r...));
}
template 
T sml(const T &f, const R &... r) {
    return sml(f, sml(r...));
}
void debug_out() { cout << '\n'; }
template 
void debug_out(const T &f, const R &... r) {
    cout << f << " ";
    debug_out(r...);
}
#define debug(...) cout << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
#define LLDO
#ifdef LLDO
const char ptout[] = "%lld";
#else
const char ptout[] = "%d";
#endif
template 
void print(const T &f) {
    printf(ptout, f);
    putchar('\n');
}
template 
void print(const T &f, const R &... r) {
    printf(ptout, f);
    putchar(' ');
    print(r...);
}

const int HMOD[] = {1000000009, 1004535809};
const int64 BASE[] = {1572872831, 1971536491};
const int64 INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
const int MOD = 1e9 + 7;  // 998244353
const int MXN = 300 + 5;
const int MXE = 2e6 + 6;
int n, S;
int ar[MXN][MXN], id[MXN], inde, cnt[MXN], d[MXN], mp[MXN];
char s[MXE];
int main() {
#ifndef ONLINE_JUDGE
    freopen("D:in.in", "r", stdin);
    freopen("D:out.out", "w", stdout);
#endif
    int tim = read();
    while(tim --) {
        scanf("%d%d", &n, &S);
        scanf("%s", s);
        int tid = 0;
        for(int i = 0; i < n - 1; ++i) {
            for(int j = i + 1; j < n; ++j) {
                ar[i][j] = s[tid] - '0';
                ar[j][i] = ar[i][j];
                ++ tid;
            }
        }
        for(int i = 0; i < n; ++i) id[i] = mp[i] = 0;
        inde = 0;
        vector vs;
        int cas = 0;
        for(int i = 0; i < n; ++i) {
            if(id[i]) continue;
            vs.clear();
            vs.eb(i);
            for(int j = 0; j < n; ++j) {
                if(ar[i][j] && id[j] == 0) vs.eb(j);
                cnt[j] = 0;
            }
            // debug("point", ++cas)
            for(int x: vs) {
                for(int j = 0; j < n; ++j) {
                    if(ar[x][j]) ++ cnt[j];
                }
                // printf("%d ", x);
            }
            // printf("\n");
            int Mx = -1, Mn = INF;
            for(int j = 0; j < n; ++j) {
                Mx = max(Mx, cnt[j]);
                Mn = min(Mn, cnt[j]);
                // printf("%d ", cnt[j]);
            }
            // printf("\n");
            int mid = (Mx + 0) FFFF;
            // debug(mid)
            ++ inde;
            for(int j = 0; j < n; ++j) {
                if(id[j] == 0 && cnt[j] >= mid) {
                    id[j] = inde;
                    // printf("%d ", j);
                }
            }
            // printf("\n");
        }
        inde = 0;
        int tmp;
        for(int i = 0; i < n; ++i) {
            if(mp[id[i]-1] == 0) mp[id[i]-1] = ++ inde, tmp = inde - 1;
            else tmp = mp[id[i]-1] - 1;
            printf("%d%c", tmp, " \n"[i == n-1]);
        }
        // debug("end")
    }
#ifndef ONLINE_JUDGE
    system("pause");
#endif
    return 0;
}

你可能感兴趣的:(2020牛客暑期多校训练营(第四场)I)