2022 纪中集训 7.13 笔记
T1 GMOJ 1381. 删除
暴力模拟。
先看第一行有,但其他行没有的数,将其在第一行所在的列删去。
重复操作直到不能操作为止。
点击查看代码
#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. 书堆
从下到上放书不好看,考虑从上倒下放书。
放第一本时, \(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;
}