codeforces AIM Tech Round 4 div 2

A:开个桶统计一下,但是不要忘记k和0比较大小

#include<bits/stdc++.h>
using namespace std;
char s[1100];
int cnt[110];
int main()
{
    int k;
    scanf("%s%d", s, &k);
    int n = strlen(s);
    if(n < k) 
    {
        puts("impossible");
        return 0;
    }
    for(int i = 0; i < n; ++i)
    {
        int t = s[i] - 'a';
        ++cnt[t];
        if(cnt[t] == 1) --k;
    }
    printf("%d\n", max(k, 0));
    return 0;
}
View Code

B:很明显只能在同一行同一列,所以一行一列的方案数就是power(2,cnt)-1,减去空集的情况,但是这样每个元素会算重一次,所以要减去n*m

#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int n, m;
long long ans = 0;
int Map[N][N], row[N][N], col[N][N];
long long power(long long x, long long t)
{
    long long ret = 1;
    for(; t; t >>= 1, x = x * x) if(t & 1) ret = ret * x;
    return ret;
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j) 
        {
            scanf("%d", &Map[i][j]);
            ++row[i][Map[i][j]];
            ++col[j][Map[i][j]];
        }
    for(int i = 1; i <= n; ++i) ans += power(2ll, row[i][1]) + power(2ll, row[i][0]) - 2;
    for(int i = 1; i <= m; ++i) ans += power(2ll, col[i][0]) + power(2ll, col[i][1]) - 2;
    printf("%I64d\n", ans - (long long)n * (long long)m);
    return 0;
}
View Code

C:一个元素必须回到自己排名对应的位置,所以必然和自己对应位置上的元素连接,然后就和对应位置的元素用并查集连接,最后统计一下就行了

#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, ans;
int fa[N], a[N];
vector<int> v, vt[N];
inline int find(int x) 
{
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}
int main()
{
    scanf("%d", &n);
    ans = n;
    for(int i = 1; i <= n; ++i) 
    {
        scanf("%d", &a[i]);
        v.push_back(a[i]);
    }
    sort(v.begin(), v.end());
    for(int i = 1; i <= n; ++i) 
    {
        a[i] = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
        fa[i] = i;
    }
    for(int i = 1; i <= n; ++i)
    {
        int x = find(a[a[i]]), y = find(a[i]);
        if(x != y)
        {
            fa[find(a[i])] = x;
            --ans;
        }
    }
    for(int i = 1; i <= n; ++i) vt[find(a[i])].push_back(i);
    printf("%d\n", ans);
    for(int i = 1; i <= n; ++i)
    {
        int sz = vt[i].size();
        if(sz == 0) continue;
        printf("%d ", sz);
        for(int j = 0; j < sz; ++j) printf("%d ", vt[i][j]);
        puts("");
    }
    return 0;
}
View Code

D:随机化 考这种东西干什么 具体是先随机1000次,然后更新ans,同时记录找到的比x小的最大的数的位置,如果没有就从start更新,然后暴力向后枚举就行了

#include<bits/stdc++.h>
using namespace std;
const int N = 50010;
int n, start, x, cnt, ans, key, nxt;
vector<int> v;
int vis[N];
int main()
{
    srand(19992147 + time(0));
    scanf("%d%d%d", &n, &start, &x);
    ans = 1000000010;
    v.push_back(start);
    int size = sqrt(n);
    for(int i = 1; i <= n; ++i) v.push_back(i);
    random_shuffle(v.begin(), v.end());
    random_shuffle(v.begin(), v.end());
    random_shuffle(v.begin(), v.end());
    int i = 0;
    while(i < v.size())
    {
        if(vis[v[i]]) 
        {
            ++i;
            continue;
        }
        ++cnt;
        if(cnt == 1999) 
        {
            printf("! %d\n", ans);
            fflush(stdout);
            exit(0);
        }
        printf("? %d\n", v[i]);
        fflush(stdout);
        scanf("%d%d", &key, &nxt);
        if(key == x) 
        {
            printf("! %d\n", x);
            fflush(stdout);
            exit(0);
        }
        if(nxt == -1) 
        {
            ++i;
            continue;    
        }
        if(key < x) 
        {
            vis[nxt] = 1;
            ++i;
            continue;
        }
        if(key > x) 
        {
            vis[nxt] = 1;
            ++i;
            ans = min(ans, key);
        }
    }
    printf("! %d\n", ans);
    fflush(stdout);
    return 0;
}
View Code

感觉这个D题很无聊...

 

posted @ 2017-08-25 08:53  19992147  阅读(177)  评论(0编辑  收藏  举报