Codeforces Round #651 (Div. 2)

感觉自己无可救药了。

A题:找到小于等于n的两个不同的数的gcd最大是多少,显然是floort(n/2)。设这两数是a * gcd, b * gcd然后gcd(a,b) = 1,那么gcd要尽量大,不妨就a = 1,b  = 2。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <map>
 7 #include <cmath>
 8 #include <queue>
 9 #include <set>
10 #define rep(i,j,k) for(int i = j; i <= k; i++)
11 #define dow(i,j,k) for(int i = j; i >= k; i--)
12 #define fi first
13 #define se second
14 using namespace std;
15 
16 
17 typedef long long ll;
18 typedef pair<int,int> pi;
19 
20 using namespace std;
21 int t;
22 int main() {
23     cin >> t;
24     while (t--) {
25         int n;
26         cin >> n;
27         n = n / 2;
28         cout << n << endl;
29     }
30 }

B题:给定2n个数,从中去掉两个数。剩下的数配成n - 1对,然后要求这些对的和的最大gcd大于1。大于1,那就gcd等于2就好了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define dow(i,j,k) for(int i = j; i >= k; i--)
#define fi first
#define se second
using namespace std;


typedef long long ll;
typedef pair<int,int> pi;

const int N = 1005;

int n, cnt[2], t;
struct node{
    int val, i;
}a[N*2];

bool cmp(node x,node y) {
    return (x.val & 1) < (y.val & 1);
}
void solve() {
    scanf("%d", &n);
    cnt[0] = cnt[1] = 0;
    rep(i,1, n * 2) scanf("%d", &a[i].val), a[i].i = i,cnt[a[i].val & 1]++;
    sort(a + 1, a + n * 2 + 1, cmp);
    if (cnt[1] & 1) {
        for(int i = 2; i < n * 2; i+=2) {
            printf("%d %d\n", a[i].i, a[i+1].i);
        }
        return;
    }
    for(int i = 1; i < n * 2 - 1; i+=2) {
        printf("%d %d\n", a[i].i, a[i+1].i);

    }
    return ;
}

int main() {
    scanf("%d", &t);
    while(t--) {
        solve();
    }
}

C题:game题,给一个数n,每次可以减1,如果有奇数因子可以除以奇数因子(包括本身),轮流操作,到1就输了。不知道有什么好做法,写了一堆if。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define dow(i,j,k) for(int i = j; i >= k; i--)
#define fi first
#define se second
using namespace std;


typedef long long ll;
typedef pair<int,int> pi;

const int N = 1005;

int dp[N];
bool isprime(int x) {
    for(int i = 2; i * i <= x; i++) {
        if (x % i == 0) return 0;
    }
    return 1;
}
int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        int n;
        scanf("%d", &n);
        if (n == 1) {
            printf("FastestFinger\n");
        }
        else if (n == 2) {
            puts("Ashishgup");
        }
        else if (n & 1) {
            puts("Ashishgup");
        }
        else{
            int cnt = 0;
            while (n % 2 ==0) cnt++, n /= 2;
            if (n == 1) {
                puts("FastestFinger");
            }
            else if (cnt == 1) {
                if (isprime(n)) puts("FastestFinger");
                else puts("Ashishgup");
            }
            else puts("Ashishgup");
        }
    }
}

D题:从一个数组里找一个长度为k的子序列,子序列的代价是,子序列的奇数位和偶数位中的最大值中的较小的值。猜测二分贪心是个好做法,然后过了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define dow(i,j,k) for(int i = j; i >= k; i--)
#define fi first
#define se second
using namespace std;


typedef long long ll;
typedef pair<int,int> pi;

const int N = 200005;

int n, k;
int a[N];

bool solve(int x) {
    int f = 1;
    int cnt = 0;
    rep(i,1,n) {
        if (cnt % 2 == 0) cnt++;
        else if (a[i] <= x) cnt++;
    }
    if (cnt >= k) return 1;
    cnt = 0;
    rep(i,1,n) {
        if (cnt & 1) cnt++;
        else if(a[i] <= x) cnt++;
    }
    if (cnt >= k) return 1;
    return 0;
}

int main() {
    scanf("%d %d", &n, &k);
    rep(i,1,n) scanf("%d", &a[i]);
    int l = 1, r = 1e9;
    while (l < r) {
        //cerr << l << " " << r << endl;
        int mid = (l + r) >> 1;
        if (solve(mid)) r = mid;
        else l = mid + 1;
    }
    printf("%d\n", l);
}

E题:给你两个长度相等的01串,每次可以选择第一个串中的一个子序列,对子序列进行循环右移(不太会简单描述这个操作),然后问最少多少次可以让两个串一样,或者无法实现。

如果两个串01数量不想等就不行,否则就可以。而且我们直接忽视掉已经匹配的位置。然后第一个串就是一堆01,现在要让0到1的位置,1到0的位置。最直接的方法直接配对然后全部循环右移即可。

01可以一次变10。发现010101可以一次变101010也就是说交替的01一次做能减少我们的操作次数。然后就找一下每个0能不能找到交替的1。然后就瞎写了写就莫名其妙过了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define dow(i,j,k) for(int i = j; i >= k; i--)
#define fi first
#define se second
using namespace std;


typedef long long ll;
typedef pair<int,int> pi;

const int N = 1e6 + 100;
int n;
char s[N], t[N];
int a[N];
int tot;
int ans;
//int lens, lent
int cnts, cntt;
int main() {
    scanf("%d", &n);
    scanf("%s", s + 1);
    scanf("%s", t + 1);
    rep(i,1,n) if (s[i] == '1') cnts++;
    rep(i,1,n) if (t[i] == '1') cntt++;
    if (cnts != cntt) {
        puts("-1");
        return 0;
    }
//    int tot = 0;
    rep(i,1,n) {
        if (s[i] == t[i]) continue;
        a[++tot] = s[i] - '0';
    }
    ans = tot;
    //cerr << tot << "!!!" << endl;
    //rep(i,1,tot) cerr << a[i] << " "; cerr << endl;
    int j = 1;
    rep(i,1,tot) {
        if (a[i] != 0) continue;
        j = max(i, j);
        while (a[j] == 0 && j <= tot) j++;
        if (j <= tot) {
            ans--;
            j++;
        }
    }
    j = tot;
    dow(i,tot,1) {
        if (a[i] != 0) continue;
        j = min(i, j);
        while (a[j] == 0 && j >= 1) j--;
        if (j >= 1) {
            ans --;
            j--;
        }
    }
    printf("%d\n", ans);
}

f:一个树上,有两个hidden的点。每次询问一个点集,返回到两点距离之和最小的一个点和到两点的距离之和。11次之内搞出来。1000个点

并不会做。然后就等第二天看题解了。

询问所有点,找出两点间路径上的一个点,然后二分,询问深度为mid的所有点,如果说返回的距离大于第一次询问的点,深度就过深了,然后10次内就能搞出某个hidden的点,然后就知道另一个点的深度再询问一次就好。

如果两点距离为d,那么至少有一个点深度是ceil(d / 2),那么就相当于使二分的边界少了一半,11次就能搞定。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define dow(i,j,k) for(int i = j; i >= k; i--)
#define fi first
#define se second
using namespace std;


typedef long long ll;
typedef pair<int,int> pi;

const int N = 1005;

struct edge{
    int to,next;
}e[N << 1];
int n, cnt, h[N];
int dep[N];
int rt, d;
pi ans[N];
int vis[N];
void add(int u,int v) {
    e[++cnt] = (edge) {v, h[u]}; h[u] = cnt;
}

void dfs(int x) {
    for (int i = h[x]; i; i = e[i].next) {
        int v = e[i].to;
        if (!dep[v] && v != rt) dep[v] = dep[x] + 1, dfs(v);
    }
}
void dfs2(int x, vector<int> &cnt, int dis) {
    vis[x] = 1;
    if(dis == d) {
        cnt.push_back(x);
        return ;
    }
    for (int i = h[x]; i; i = e[i].next) {
        int v = e[i].to;
        if (!vis[v]) dfs2(v, cnt, dis + 1);
    }
}
void solve() {
    cnt = 0;
    int x, y;
    int a = 0, b = 0;
    memset(h, 0, sizeof(h));
    memset(dep, 0, sizeof(dep));
    memset(ans, 0, sizeof(ans));
    scanf("%d", &n);
    rep(i,1,n-1) {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v); add(v, u);
    }
    printf("? %d ", n);
    rep(i,1,n) printf("%d ", i); puts("");
    fflush(stdout);
    scanf("%d %d", &rt, &d);
    int l = (d + 1) / 2, r = d;
    dfs(rt);
    ans[0] = make_pair(rt, d);
    while(1) {
        int mid = (l + r + 1) >> 1;
        if (!ans[mid].fi) {    
            vector<int> temp;    
            rep(i,1,n) if (dep[i] == mid) temp.push_back(i);
            int cnt = temp.size();
            if (cnt == 0) {
                r = mid - 1;
                continue;
            }
            printf("? %d ", cnt);
            rep(i,0,cnt-1) printf("%d ", temp[i]); puts("");
            fflush(stdout);
            scanf("%d %d", &x, &y);
            ans[mid] = make_pair(x, y);
        }

        if (ans[mid].se > d) r = mid - 1;
        else l = mid;
        if (l == r && l == mid) {a = ans[l].fi; break;}
    } 


    vector<int> temp;
    memset(vis, 0, sizeof(vis));
    dfs2(a, temp, 0);
    int cnt = temp.size();
    if (cnt == 1) b = temp[0];
    else {
        printf("? %d ", cnt);
        rep(i,0, cnt - 1) printf("%d ", temp[i]); puts("");
        fflush(stdout);
        scanf("%d %d", &x, &y);
        b = x;
    }
    printf("! %d %d\n", a, b);
    string s;
    fflush(stdout);
    cin >> s;
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        solve();
    }
}

 

 

感觉自己明明d、e都不会做就是瞎蒙对的……

然后交互题尽量应该把交互的过程封装一下。

 

posted @ 2020-06-21 17:04  iwwi  阅读(276)  评论(0)    收藏  举报