A. Mike and Cellphone
模拟即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
char s[20];
int main(){
int n;
while(scanf("%d", &n) != EOF){
scanf("%s", s);
int ans = 0, len = strlen(s);
for(int i = 0; i < len; i++)
if(s[i] == '1' || s[i] == '2' || s[i] == '3'){ ans++; break;}
for(int i = 0; i < len; i++)
if(s[i] == '1' || s[i] == '4' || s[i] == '7') { ans++; break;}
for(int i = 0; i < len; i++)
if(s[i] == '3' || s[i] == '6' || s[i] == '9') { ans++; break;}
for(int i = 0; i < len; i++)
if(s[i] == '7' || s[i] == '9' || s[i] == '0') { ans++; break;}
if(ans == 4){
printf("YES\n");
continue;
}
ans = 0;
for(int i = 0; i < len; i++) if(s[i] == '0') ans = 3;
for(int i = 0; i < len; i++) if(s[i] == '1' || s[i] == '2' || s[i] == '3') { ans++; break;}
if(ans == 4) printf("YES\n");
else printf("NO\n");
}
return 0;
}
B - Mike and Shortcuts
简单bfs
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 2e5 + 100;
const int INF = 0x3f3f3f3f;
int a[maxn], dist[maxn];
void solve(int n){
memset(dist, INF, sizeof(dist));
dist[1] = 0;
queue <int> que;
que.push(1);
while(!que.empty()){
int cur = que.front(); que.pop();
if(dist[a[cur]] > dist[cur] + 1){
que.push(a[cur]);
dist[a[cur]] = dist[cur] + 1;
}
if(cur+1 <= n && dist[cur+1] > dist[cur] + 1){
que.push(cur+1);
dist[cur+1] = dist[cur] + 1;
}
if(cur-1 > 0 && dist[cur-1] > dist[cur] + 1){
que.push(cur-1);
dist[cur-1] = dist[cur]+1;
}
}
}
int main(){
int n;
while(scanf("%d", &n) != EOF){
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
solve(n);
for(int i = 1; i <= n; i++)
printf("%d ", dist[i]);
printf("\n");
}
return 0;
}
C - Mike and Chocolate Thieves
二分即可,找到所得到的值,然后最后判断二分得到的值是否符合题意即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
const LL maxn = 1e6;
LL judge(LL mid){
LL ans = 0;
for(LL i = 2; i <= maxn; i++){
LL cnt = i*i*i;
if(mid/cnt == 0) break;
ans += mid/cnt;
}
return ans;
}
int main(){
LL m;
while(scanf("%I64d", &m) != EOF){
LL l = 8, r = 1e18;
while(l < r){
LL mid = (l+r)/2;
if(judge(mid) >= m) r = mid;
else l = mid+1;
}
if(judge(r) != m) printf("-1\n");
else printf("%I64d\n", r);
}
return 0;
}
D - Friends and Subsequences
这道题我们会发现如果左端点已经定一下来了,那么很明显在右端点不断增大的情况下,该区间的最最大值是单调不减的,另一个区间的最小值是单调不增的,那么对于这种情况很明显二分即可。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 2e5+100;
#define LL long long
int n;
int dp1[maxn][20], dp2[maxn][20];
void RMQ_init(){
for(int j = 1; (1<<j) <= n; j++)
for(int i = 1; (i+(1<<j)-1) <= n; i++){
dp1[i][j] = max(dp1[i][j-1], dp1[i+(1<<(j-1))][j-1]);
dp2[i][j] = min(dp2[i][j-1], dp2[i+(1<<(j-1))][j-1]);
}
}
int query1(int l,int r){ //查询
int cnt = log2(r-l+1), len = 1<<cnt;
return max(dp1[l][cnt], dp1[r-len+1][cnt]);
}
int query2(int l,int r){ //查询
int cnt = log2(r-l+1), len = 1<<cnt;
return min(dp2[l][cnt], dp2[r-len+1][cnt]);
}
int main(){
while(scanf("%d", &n) != EOF){
for(int i = 1; i <= n; i++) scanf("%d", &dp1[i][0]);
for(int i = 1; i <= n; i++) scanf("%d", &dp2[i][0]);
RMQ_init();
int l, r;
LL ans = 0;
for(int i = 1; i <= n; i++){
l = i, r = n;
while(l < r){
int mid = (l+r)/2;
if(query1(i, mid) >= query2(i, mid)) r = mid;
else l = mid+1;
}
int temp1 = r;
l = i, r = n;
while(l < r){
int mid = (l+r+1)/2;
if(query1(i, mid) <= query2(i, mid)) l = mid;
else r = mid-1;
}
int temp2 = l;
if(temp1 != temp2) ans += temp2 - temp1 + 1;
else if(query1(i, temp1) == query2(i, temp2)) ans++;
}
printf("%I64d\n", ans);
}
return 0;
}