题目链接
A
题意是说有一个食堂,共 n n n层,但是有 K K K层关闭了,现在A在第 s s s层,问A至少爬几层楼梯可以吃饭。
思路:
这题其实暴力完事,然后主要说一下set做法。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define read(x) scanf("%d",&x)
#define Read(x,y) scanf("%d%d",&x,&y)
#define gc(x) scanf(" %c",&x);
#define mmt(x,y) memset(x,y,sizeof x)
#define write(x) printf("%d\n",x)
#define FAST ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x3f3f3f3f
#define ll long long
#define mod 998244353
const int N = 1e6+5;
int main(){
FAST
int t;
cin >> t;
set<int> st;
while(t--){
st.clear();
int n,s,k;
cin >> n >> s >> k;
while(k--){
int a;
cin >> a;
st.insert(a);
}
int ans = 0;
while((st.count(s + ans)||s + ans > n) && (st.count(s - ans)|| s - ans <=0)) ans ++;
cout<<ans<<endl;
}
}
B
题意: J J J 有 s s s个对手,每个问题可以有t个人回答错误,他便可获得 t s \dfrac{t}{s} st的收益,问 J J J的最大收益是多少。
思路:贪心,每次令 t = 1 t=1 t=1,然而我不会证明。只是凭感觉。
int main(){
long double sum = 0;
long double a;
int t;
cin >> t;
a = 1;
for(int i = 1;i <= t;++i){
sum += (long double)1/a;
a ++;
}
cout<<fixed<<setprecision(12)<<sum<<endl;
}
C
题意
:
有一个 2 ∗ n 2 * n 2∗n的矩阵,初始时每一个矩阵中每一个方格都是可通过的,然后有 q q q个询问,每次给出一个方格的坐标,使得这个方格的状态翻转(通过变不通过或者不通过变通过),对于每个查询问你是否可以从 ( 1 , 1 ) (1,1) (1,1)到 ( 2 , n ) (2,n) (2,n)。
思路:
这个题目Wa了五遍。。。
一开始的思路是想怎么才能不通过,只有在第一行和第二行都有不可通过的方格且它们在同一列或者相邻的列,那么我们就用一个变量统计这样不能通过的对数即可。然后一直Wa,后来通过乱输,终于找到一个反例,最后乱搞过了。思维还不是很缜密。
看了别人代码我忽然明白过来,我少统计了这种互阻对,我是这样写的。
if(s[a][b-1]||s[a][b]||s[a][b+1]) sum --;
应该把 i f if if拆开,
if(s[a][b-1]) sum ++;
if(s[a][b]) sum ++;
if(s[a][b+1]) sum ++;
哈呼。。。。这么说我乱搞是正确的,乱搞如下
#define read(x) scanf("%d",&x)
#define Read(x,y) scanf("%d%d",&x,&y)
#define gc(x) scanf(" %c",&x);
#define mmt(x,y) memset(x,y,sizeof x)
#define write(x) printf("%d\n",x)
#define INF 0x3f3f3f3f
#define ll long long
#define mod 998244353
const int N = 1e6+5;
int s[4][N];
int main(){
int n,q;
Read(n,q);
int sum = 0;
for(int i = 1;i <= q;++i){
int a,b;
Read(a,b);
if(s[a][b] == 0){
s[a][b] = 1;
if(a == 1) a ++;
else a --;
sum += s[a][b-1]+s[a][b]+s[a][b+1];//统计互阻对
}
else {
s[a][b] = 0;
if(a == 1) a ++;
else a --;
sum -= s[a][b-1]+s[a][b]+s[a][b+1];//消除互阻对
}
if(sum == 0) puts("Yes");
else puts("No");
}
}
D
题意:
Aroma 要找回丢失的记忆,这些记忆化为一个个数据点分布在二维平面,且
初始数据点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)
其余的分布 = ( a x ⋅ x i − 1 + b x , a y ⋅ y i − 1 + b y ) =(a_x⋅x_{i−1}+b_x,a_y⋅y_{i−1}+_by) =(ax⋅xi−1+bx,ay⋅yi−1+by)
然后他只能进入这个二维平面 t t t秒,问你最多可以收集多少数据点。
思路:
昨天没思路,没有分析出这些点之间的关系以及数据的范围大小。
已知, a x a_x ax和 a y a_y ay都是大于等于2的,且数据点的坐标最大 1 e 16 1e^{16} 1e16,所以这些点最多也不会超过60个,这是前提。
然后数据点的坐标按标号是逐渐递增 的,且如果收集数据点肯定要选一段收集,这样是最优的(感性)
由曼哈顿距离 d ( l − > z − > r ) = d(l->z->r)= d(l−>z−>r)= d ( l , z ) + d ( z , r ) d(l,z)+d(z,r) d(l,z)+d(z,r),由于递增,所以 = d ( l , r ) =d(l,r) =d(l,r)
我们枚举收集区间 ( l , r ) (l,r) (l,r),已知起点 ( x s , y s ) (x_s,y_s) (xs,ys),所以花费的时间为 m i n ( d ( s − > l ) + d ( l , r ) , d ( s − > r ) + d ( l , r ) min(d(s->l)+d(l,r),d(s->r)+d(l,r) min(d(s−>l)+d(l,r),d(s−>r)+d(l,r)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define read(x) scanf("%d",&x)
#define Read(x,y) scanf("%d%d",&x,&y)
#define gc(x) scanf(" %c",&x);
#define mmt(x,y) memset(x,y,sizeof x)
#define write(x) prllf("%d\n",x)
#define FAST ios::sync_with_stdio(false);cin.tie(0);
#define INF 0x3f3f3f3f
#define ll long long
#define mod 998244353
const ll N = 1e6+5;
pair<ll,ll> pLL[100];
int main(){
ll x0,y0,ax,ay,bx,by;
cin >>x0 >>y0>>ax>>ay>>bx>>by;
ll xs,ys,t;
cin >>xs >>ys >> t;
pLL[0].first = x0,pLL[0].second = y0;
ll k = 1;
for(;;k ++){
pLL[k].first = ax *pLL[k-1].first +bx;
pLL[k].second = ay * pLL[k-1].second + by;
if(pLL[k].first - xs + pLL[k].second - ys > t) break;
}
k --;
ll ans = 0;
for(ll i = 0;i <= k;++i){
for(ll j = i ;j <= k;++j){
ll len = pLL[j].first - pLL[i].first + pLL[j].second - pLL[i].second;
ll l = abs(xs - pLL[i].first) + abs(ys - pLL[i].second);
ll r = abs(xs - pLL[j].first) + abs(ys - pLL[j].second);
if(len + l <= t || len + r <= t) ans = max(ans,j - i + 1);
}
}
cout<<ans<<endl;
}