2022 纪中集训 7.13 笔记

T1 GMOJ 1381. 删除

image

暴力模拟。

先看第一行有,但其他行没有的数,将其在第一行所在的列删去。

重复操作直到不能操作为止。

点击查看代码
#include <bits/stdc++.h>
using namespace std;

const int N = 100010;

int lin1[N], lin2[N], lin3[N];
int num2[N], num3[N];
int n, dele = 0, ans = 0;

int main()
{
    cin >> n;
    for (int i = 1; i <= 3; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (i == 1)
                cin >> lin1[j];
            else if (i == 2)
                cin >> lin2[j], num2[lin2[j]]++;
            else if (i == 3)
                cin >> lin3[j], num3[lin3[j]]++;
        }
    }
    do
    {
        dele = 0;
        for (int i = 1; i <= n; i++)
        {
            if (lin1[i] && ((!num2[lin1[i]]) || (!num3[lin1[i]])))
            {
                ans++;
                lin1[i] = 0;
                num2[lin2[i]]--;
                num3[lin3[i]]--;
                dele = 1;
            }
        }
    } while (dele);
    cout << ans;
}

T2 GMOJ 1897. 书堆

image

从下到上放书不好看,考虑从上倒下放书。

放第一本时, \(L\) 无限接近 \(\sum^{1}_{i=1} \frac{1}{i} \times \frac{1}{2} M\)
放第二本时,\(L\) 无限接近 \(\sum^{2}_{i=1} \frac{1}{i} \times \frac{1}{2} M\)

\(\cdots\)

放第 \(n\) 本时, \(L\) 无限接近 \(\sum^{n}_{i=1} \frac{1}{i} \times \frac{1}{2} M\)

于是问题转化为了求调和级数的值。

根据调和级数 \(\sum_{i=1}^{n}\) 和自然对数函数 \(\ln(n)\)\(n\) 接近无穷大时,差值为欧拉常数 \(0.5772156649\)

于是可以在 \(n < 10^7\) 时暴力,其他时候采用 \(\sum_{i=1}^{n} \approx \ln(n) + 0.5772156649\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;

const double eps = 1e-6;
const double euler = 0.5772156649015328;

int main()
{
    double n, m;
    cin>>n>>m;

    if(n > 1e7) cout<<round((log(n) + euler) * m / 2 - 0.5 - eps) << endl;
    else
    {
        double e = 0;
        for(int i=1;i<=n;i++) e += 1.0/i;
        cout<<round(e * m / 2 - 0.5 - eps);
    }

    return 0;
}

T3 GMOJ 2643. 六边形

考虑将六边形转化用二维数组存储。

由于在二维数组中有 \(8\) 个相邻点,然而在六边形中只有 \(6\) 个相邻点。

1 1 0
1 x 1
0 1 1

考虑在将二维数组中右上和左下的点视为不与 \(x\) 点相邻。

然后暴力模拟每个点应该放那个数即可。

\(n\) 只有 \(10000\),暴力预处理之后完全没问题。

点击查看代码
#include <bits/stdc++.h>
using namespace std;

typedef pair<int,int> PII;
#define times first
#define num second

const int N = 1005;
const int dx[6] = {1,1,0,-1,-1,0}, dy[6] = {0,1,1,0,-1,-1};

inline int read()
{
    register int x = 0, f = 1;
    register char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
    return x * f;
}

int ans[20005], a[N][N], now;
PII p[10];
bool st[10];

void f(int x,int y)
{
    memset(st, 0, sizeof st);
    sort(p+1,p+1+5);
    for(int i=0;i<6;i++) st[a[x+dx[i]][y+dy[i]]] = 1;
    for(int i=1;i<=5;i++)
    {
        if(!st[p[i].num])
        {
            p[i].times++;
            a[x][y] = p[i].num;
            ans[now] = p[i].num;
            break;
        } 
    }
}

int main()
{
    int x = 500, y = 500, k = 1;
    for(int i=1;i<=5;i++) p[i].num = i;
    a[x][y] = 1, ans[++now] = 1, p[1].times ++;

    //1 1 0
    //1 1 1
    //0 1 1
    while(now < 10005)
    {
        x ++, y ++;
        for(int i=1;i<=k;i++) now ++, x --, f(x, y); // upper
        for(int i=1;i<=k;i++) now ++, x -- , y -- ,f(x, y);// upper left
        for(int i=1;i<=k;i++) now ++, y --, f(x, y); // left
        for(int i=1;i<=k;i++) now ++, x ++, f(x ,y); // down 
        for(int i=1;i<=k;i++) now ++, x ++, y++ , f(x, y); // down right
        for(int i=1;i<=k;i++) now ++, y ++, f(x, y); // right
        k++;
    }

    // for(int i=1;i<=10000;i++) printf("%d%c",ans[i]," \n"[i%5 == 0]);

    int T = read();
    while(T--) printf("%d\n", ans[read()]);

    return 0;
}
posted @ 2022-07-13 19:01  BorisDimitri  阅读(25)  评论(0编辑  收藏  举报