传送门
A ConneR and the A.R.C. Markland-N
B JOE is on TV!
C NEKO’s Maze Game
D Aroma’s Search
A ConneR and the A.R.C. Markland-N
题意:有n层楼,每层都有饭店,一个住在s层的人想要吃饭,但是有k家饭店已经关门,告诉你是那k家。问离s层最近的还在营业的有多远(原题是要走多少楼数)?
思路:题目给了k的范围,直接枚举s-1010,到s+1010,符合条件的正在营业的饭店找最近值即可。
当时傻逼的吧s写成了n,wa了两发,实在沙雕。
#include<algorithm>
#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<map>
#include<cstdio>
using namespace std;
const int N = 1e6+10;
typedef long long ll;
void solve()
{
map<int, int> vis;
int n, s, k, x;
scanf("%d%d%d", &n, &s, &k);
for(int i = 1; i <= k; ++i) {
scanf("%d", &x);vis[x] = 1;
}
int mi = 2000;
for(int i = s-1010; i <= s+1010; ++i) {
if(i<1||i>n||vis[i]) continue;
mi = min(mi, abs(s-i));
}
printf("%d\n", mi);
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
solve();
return 0;
}
B JOE is on TV!
题意:有n个对手,每局游戏淘汰t个可获得t/n的钱。
思路: 贪心,每次只淘汰一个的方案最优。
#include<algorithm>
#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<map>
#include<cstdio>
using namespace std;
const int N = 1e6+10;
typedef long long ll;
void solve()
{
int n;
cin>>n;
double mi = 0.0;
for(int i = 1; i <= n; ++i) {
mi +=(1.0)/(i*1.0);
}
cout<<mi<<endl;
}
int main()
{
// int t;
// cin >> t;
// while(t--)
solve();
return 0;
}
C NEKO’s Maze Game
题意:现有一个2*n的方格,初始状态都是平地,你只能想两个格子共用一面的来回移动,也就是上下左右。在q个时刻,坐标为li,ri的格子地形会变化,平地变熔浆,熔浆变平地,问在q时刻后是否还能从(1,1)走到(2,n)。输出yes,no。
思路: 我们会发现如果一个格子是熔浆,位置是(1,a),若(2,b),|a-b|<=1的格子也是熔浆,画一下就能看出来,这是走不了。如果(2,a),对应(1,b)的格子。此时我们计算有多少种情况不能走,如果结果为0就是YES,反之就是NO。我们用map来进行记录,用一个变量来存储不行的情况数目,如果多了一个熔浆,看多了多少种情况,少了一个熔浆,少了多少种情况就行。
#include<algorithm>
#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<map>
#include<cstdio>
#include<vector>
#include<stdlib.h>
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
typedef long long ll;
typedef pair<int, int> pii;
int n, t;
map<pii, bool> vis;
int sum = 0;
bool ok(int x, int y)
{
if(x<1||x>2||y<1||y>n||!vis[pii(x,y)]) return false;
return true;
}
void solve()
{
int x, y;
scanf("%d%d", &x, &y);
int cnt = 0;
vis[pii(x, y)] = !vis[pii(x, y)];
int tx = x, ty = y;
for(int j = -1; j <= 1; ++j) {
int dx = 2, dy = ty+j;
if(tx == 2) dx = 1;
cnt += (ok(dx, dy));
}
if(vis[pii(x, y)]) sum += cnt;
else sum -= cnt;
if(sum == 0)
puts("YES");
else puts("NO");
}
int main()
{
scanf("%d%d", &n,&t);
while(t--)
solve();
return 0;
}
D Aroma’s Search
题意:一个人在t时间内能得到多少数据节点。第二个条件是用来求节点的,是一个公式。
思路: 由题意可知,节点是向右上角发展的,也就是说l到r节点的距离和得到l到r节点的最短距离是相同的,所以最大节点数一定是连续的区间。计算可得节点数较少,先计算出可能的节点坐标,然后枚举可达到的节点的连续区域,求最大即可。
#include<algorithm>
#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<map>
#include<cstdio>
using namespace std;
const int N = 1e6+10;
typedef long long ll;
const ll INF = 1e17;
ll x[N],y[N];
ll ax,ay,bx,by,a,b,t;
int main()
{
cin>>x[0]>>y[0]>>ax>>ay>>bx>>by;
int n=0;
for(;x[n]<INF && y[n]<INF;++n)
{
x[n+1]=x[n]*ax+bx,y[n+1]=y[n]*ay+by;
if(x[n+1]>=INF|| y[n+1]>=INF) break;
}
cin>>a>>b>>t;
int ans=0;
for(int l=0;l<=n;++l)
{
for(int r=l;r<=n;++r)
{
unsigned long long to = min(abs(a-x[l])+abs(b-y[l]), abs(a-x[r])+abs(b-y[r]));
to+=abs(x[l]-x[r])+abs(y[l]-y[r]);
if(to<=t) ans=max(ans,r-l+1);
}
}
cout<<ans<<endl;
return 0;
}