ICPC Asia Xuzhou 2019[网络赛]——[ABEG]

问题虫洞——A: Who is better?

 

黑洞内窥:

先求一组同余方程(CRT),然后斐波那契博弈:

 

思维光年:

题目 == 题解

 

ACcode:

#include<stdio.h>
#include<iostream>
#include<map>
#include<algorithm>
#include<cstring>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
#define MAXN 1000025
#define INF 0x3f3f3f3f//将近int类型最大数的一半,而且乘2不会爆int
#define MOD 1000000007 // MOD%4 = 3
const double pi = acos(-1.0);
const double eps = 1e-6;

ll b[MAXN], w[MAXN];		//w为除数,b是余数
ll exgcd(ll a, ll b, ll &x, ll &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    int gcd = exgcd(b, a%b, x, y);
    int t = x;
    x = y;
    y = t - a/b*y;
    return gcd;
}

ll China(ll B[], ll W[], ll k) //W为除数,B是余数
{
    ll i, a, b, c, d, x, y, t;
    for(i=1; i<k; ++i)
    {
        a = W[i-1], b = W[i];
        c = B[i] - B[i-1];
        d = exgcd(a, b, x, y);
        if(c%d)
            return -1;
        t = b/d;
        x = (x*(c/d)%t+t)%t;
        B[i] = B[i-1] + W[i-1]*x;
        W[i] = W[i]/d*W[i-1];
    }
    return B[k-1];
}

ll f[75];
void init()
{
    f[1] = 1;
    f[2] = 2;
    for(int i=3; i<=73; ++i)
        f[i] = f[i-1] + f[i-2];
        //cout << f[73] << '\n';
}

int main()
{
    init();
    ll k, ans;
    scanf("%lld", &k);
    for(int i=0; i<k; ++i)
        scanf("%lld %lld", &w[i], &b[i]);

    ans = China(b, w, k);
    if(ans == -1) puts("Tankernb!");
    else
    {
        int flag = 0;
        for(int i=1; i<=73; ++i)
            if(ans == f[i])
            {
                flag = 1;
                break;
            }
        if(flag) puts("Lbnb!");
        else puts("Zgxnb!");
    }
    return 0;
}

 

问题虫洞——B:so easy

 

黑洞内窥:

给你n个点m个操作,每次操作可以选择1或2

1:删除x

2:查询x, 若x已被删除,则输出x+1,若x+1也被删除,则继续查找

 

思维光年:

我不知道为什么,我们队也是用并查集查找,但就是T了,而且还是2001ms,,

后来,,,划重点:

使用map.count()的查找查找复杂度会更低。。。。。

(老实说,用set暴力都可以过,我枯了~~~~~~~我队wa了18发,鬼™知道换成count就过了,一看题解我们都sb了)

#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<string>
#include<map>
using namespace std;

map<int,int>q;
int n,m,t,x;

int tofind(int w)
{
    if(!q.count(w)) return w;
    return q[w] = tofind(q[w]);
}
int main()
{
    scanf("%d%d",&n,&m);
    while(m--)
    {
        scanf("%d%d",&t,&x);
        if(t == 1) q[x] = tofind(x + 1);
        if(t == 2) printf("%d\n",tofind(x));
    }
    return 0;
}

 

问题虫洞——E:XKC's basketball team

 

黑洞内窥:

给出一个序列A,和一个值m,

求比第i个数ai+m还要大的数且这个数尽可能的靠右边,设为j, 若没有则为-1。

输出n个数,每个数代表i与j之间的数.

 

思维光年:

栈维护+二分查找

(队友嫌线段树麻烦,,,然后就这样被她A掉了。。。)

 

ACcde:

#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#include<string>
#include<map>
using namespace std;

const int maxn = 1e6 + 10;
int n,m,tot;
int a[maxn],b[maxn],c[maxn],ans[maxn];

int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n; ++i)
    {
        scanf("%d",&a[i]);
        ans[i] = -1;
    }
    tot = 0;
    for(int i = n;i >= 1; --i)
    {
        int p = lower_bound(c + 1,c + tot + 1,a[i] + m) - c;
        if(p <= tot) ans[i] = b[p] - i - 1;
        if(a[i] > c[tot]) b[++tot] = i,c[tot] = a[i];
    }
    for(int i = 1;i < n; ++i) printf("%d ",ans[i]);
    printf("-1\n");
    return 0;
}

 

问题虫洞——G: Center

 

黑洞内窥:

给你一些点,你需要定一个中心点,

使得你可以尽可能少的添加一些点,

使得添加这些点之后的点集中两两关于这个中心点对称

 

思维光年:

一开始看到点数只有1000的时候就想着可能是暴力求解,

但是考虑到后面遍历的点数敲不出来,,(还是自己太菜。。)

所以就没有敲,后来发现是大水题。。。。

 

理性的思考:

有n个点,每个点都与其它所有的点(包括它自己)连线,求所有生成的中点,

然后我们从这些中点当中找出出现次数最多的那个就行,

设它的出现次数为num,则答案就为n-num。

 

ACcode:

//#include<bits/stdc++.h>
//std::ios::sync_with_stdio(false);
#include  <stdio.h>
#include <iostream>
#include<algorithm>
#include      <set>
#include      <map>
#include    <queue>
#include    <stack>
#include   <string>
#include   <math.h>
#include   <vector>
#include  <cstring>
#include <stdlib.h>
#include <string.h>
using namespace std;
typedef long long ll;
#define MAXN 1000005
#define INF 0x3f3f3f3f//将近ll类型最大数的一半,而且乘2不会爆ll
const ll mod = 998244353;
#define mem(a, b) memset(a, b, sizeof(a))

pair<int, int>point[1005];
map<pair<int, int>, int>mp;
int main()
{
    int n, ans = 0;
    cin >> n;
    for(int i=1; i<=n; ++i)
        scanf("%d %d", &point[i].first, &point[i].second);
    for(int i=1; i<=n; ++i)
    {
        for(int j=1; j<=n; ++j)
        {
            pair<int, int>p;            //*2是为了防止小数
            p.first = (point[i].first*2+point[j].first*2)/2;
            p.second = (point[i].second*2+point[j].second*2)/2;
            mp[p]++;
            if(mp[p] > ans) ans=mp[p];
        }
    }
    cout << n-ans << '\n';
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章