A. Watermelon by miamiao
description: 给出一个西瓜的质量 w ,问能不能把这个西瓜分成两份,每一份的质量都是正偶数。
#include<bits/stdc++.h>
using namespace std;
int n;
int main()
{
scanf("%d",&n);
if (n>=4&&n%2==0)puts("YES");
else puts("NO");
}
评价:低档题。签到。
B. Bayan Bus by zhber
solution: 直接暴力模拟。
#include<bits/stdc++.h>
using namespace std;
char s[6][30]={"+------------------------+",
"|#.#.#.#.#.#.#.#.#.#.#.|D|)",
"|#.#.#.#.#.#.#.#.#.#.#.|.|",
"|#.......................|",
"|#.#.#.#.#.#.#.#.#.#.#.|.|)",
"+------------------------+"};
int k,x,y;
int main()
{
scanf("%d",&k);
x=y=1;
for (int i=1;i<=k;i++)
{
s[x][y]='O';
if(x==4)x=1,y+=2;
else if (x==2&&y!=1)x=4;
else x=x+1;
}
for (int i=0;i<6;i++)puts(s[i]);
}
评价:低档题。签到。
C. Spyke Talks by sadyi98
description:
n
个人,每个人可以在通话也可以不在通话,如果在通话就会得到一个通话
solution:
排序后去掉
0
,统计多少个数字恰好出现了
void solve() {
int n, ans;
scanf("%d", &n);
map<int, int> m;
for (int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
m[x]++;
}
for (auto i = m.begin(); i != m.end(); i++) {
if (i->first == 0) continue;
int t = i->second;
if (t > 2) {
puts("-1");
return;
}
if (t == 2) ans++;
}
printf("%d\n", ans);
}
评价:低档题。
D. Opposites Attract by sadyi98
solution:
统计数字
k
出现的次数
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n;
ll zero,p[11],q[11];
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
int x;scanf("%d",&x);
if (!x)zero++;
else if (x>0)p[x]++;
else q[-x]++;
}
ll ans=zero*(zero-1)/2;
for (int i=1;i<=10;i++)ans+=p[i]*q[i];
printf("%lld\n",ans);
}
评价:低档题。
E. Chtholly’s request by BITtian
description:
询问前
k
小的、长度是偶数的回文数之和,答案对
solution:
显然长度是偶数的回文数是通过一个数字后面接上它的翻转数字来构造。枚举
1
到
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int k,p;
ll ans;
ll calc(ll x)
{
int d[10],len=0,temp=x;
while (temp)
{
d[++len]=temp%10;
temp/=10;
}
for (int i=1;i<=len;i++)x=x*10+d[i];
return x;
}
int main()
{
scanf("%d%d",&k,&p);
for (int i=1;i<=k;i++)ans+=calc(i)%p;
printf("%lld\n",ans%p);
}
评价:低档题。
F. Tourist’s Notes by miamiao
description:
给出一个长度为
n
的数列,限制数列中相邻的两项之差绝对值不超过1。现在确定了其中
solution: 相邻位置数字之差不超过1,如果有两个相邻的确定大小的数字,距离之差小于大小之差,即 |posi−posi+1|<|aposi−aposi+1| ,那么一定无解。接下来从第一个确定位置往前、最后一个确定位置往后的地方没有限制,答案初值为 max{apos1+pos1−1,aposm+n−posm} 。接着考虑从 aposi 走到 aposi+1 多出来的步数往上走来获得更大的数字,考虑到要折返,用 max{aposi,aposi+1}+rest2 更新答案即可。
评价:中低档题。思路不是很难想到。定位是选手在比赛一小时内能写出来的题。
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
const int maxn = 1e5 + 10;
/* head */
int a[maxn], b[maxn];
inline void solve() {
int n, m;
scanf("%d%d", &n, &m);
int ans = 0;
rep(i, 1, m + 1) {
scanf("%d%d", &a[i], &b[i]);
ans = max(ans, b[i]);
}
bool ok = 1;
rep(i, 2, m + 1) {
if (a[i] - a[i - 1] < abs(b[i] - b[i - 1])) {
ok = 0;
break;
} else {
int d = a[i] - a[i - 1] - abs(b[i] - b[i - 1]);
ans = max(ans, max(b[i], b[i - 1]) + d / 2);
}
}
if (!ok) { puts("IMPOSSIBLE"); return; }
ans = max(ans, max(b[1] + a[1] - 1, b[m] - a[m] + n));
printf("%d\n", ans);
}
int main() {
solve();
return 0;
}
G. Number of Ways by zhber
description:
给一个长度为
n
的数列,满足
ll a[5000005];
int main () {
int n;
cin>>n;
if(n<3){
cout<<0;
return 0;
}
ll s = 0;
for(int i = 0; i<n; i++){
cin>>a[i];
a[i]+=a[i-1];
}
ll t = 0;
ll ans = 0;
for(int i = 0; i<n-1; i++){
if(a[i]*3 == a[n-1]*2)
ans+=t;
if(a[i]*3 == a[n-1])t++;
}
cout<<ans;
return 0;
}
评价:中档题。枚举前缀和与后缀和不难想到,但是统计的时候前后缀和不能重叠而且要留出中间部分的处理方法不容易想到。定位是选手在比赛两个小时左右可以做出来。
H. Design Tutorial: Learn from Life by zhber
n
个人坐电梯,第
评价:中档题。由于样例解释有把人送上去再放在中间楼层中转的过程,有一定误导性,因此不容易直接反应过来送上去中转和直接到目的地没有区别。但最优策略实际上不难发现,而且一旦想到最优策略立刻能意识到中转没有意义。因此定位是选手在比赛一两个小时的时候可以做出来的题目。
// by H题一血选手Natsumatsu
#include <cstdlib>
#include <iostream>
#include <cmath>
#include<algorithm>
#include <cstdio>
#include <cstring>
#include<stack>
#include <queue>
#include <functional>
using namespace std;
#define lim 1e-5
#define ll long long
//const double e = 2.718281828459;
//long long fpow(int a, int b);
#include <iostream>
#include <cmath>
#include<algorithm>
#include <cstdio>
#include <cstring>
#include<stack>
#include <queue>
#include <functional>
using namespace std;
#define lim 1e-5
#define ll long long
int m,n; char in[200], out[200];
int main()
{
priority_queue<int, vector<int>, less<int>> bg;
int a, b; int x, y;
cin >> a >> b;
int i, j;
ll sum = 0;
for(i=1;i<=a;i++)
{
cin >> x;
bg.push(x);
}
while (bg.size() >= b)
{
sum += 2 * (bg.top() - 1);
for (i = 1; i <= b; i++) bg.pop();
}
if(!bg.empty())sum += 2 * (bg.top() - 1);
cout << sum << endl;
return 0;
}
I. They Are Everywhere
solution:
如果存在一个长度为
k
的满足条件的子串,那么显然也存在长度为
评价:中高档题。
#include<bits/stdc++.h>
#define F first
#define S second
using namespace std;
typedef vector<int> vi;
typedef vector<vi> vvi;
map<char, int> toint;
map<int, char> tochar;
vvi frec;
int ind = 1;
bool check(int l, int r) {
for (int i=0;i<ind-1;++i) {
int aux = frec[i][r];
if (l > 0) aux -= frec[i][l-1];
if (aux == 0) return false;
}
return true;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n;
string s;
cin>>n>>s;
for (int i=0;i<n;++i) {
if (toint[s[i]] == 0) {
toint[s[i]] = ind;
tochar[ind] = s[i];
ind++;
}
}
frec = vvi(ind, vi(n, 0));
frec[toint[s[0]]-1][0] = 1;
for (int i=1;i<n;++i) {
for (int j=1;j<ind;++j) {
frec[j-1][i] = frec[j-1][i-1] + (s[i]==tochar[j]);
}
}
int mini = 1e8;
for (int i=0;i<n;++i) {
int left = i, right = n-1, mid, cnt = 50;
if (!check(i, n-1)) break;
while (cnt--) {
mid = (left+right)/2;
if (check(i, mid)) {
right = mid;
} else {
left = mid+1;
}
}
while(!check(i, mid))
mid--;
if (mini > mid-i+1) {
mini = mid-i+1;
}
}
cout<<mini<<"\n";
return 0;
}
J. Main Sequence by zhber
description:
有
k
种不同的括号,左括号用数字
solution: 左括号可以变右括号,但右括号不能变左括号。这说明左括号变化更多,而右括号没得变。因此考虑倒着用右括号匹配对应的左括号。如果倒着遇到一个左括号,它不能和后面的右括号匹配了,就改成右括号。从后往前维护一个栈,保证栈中只有右括号,找新括号与栈中右括号匹配。如果当前的括号与栈顶匹配就马上匹配并退栈,否则右括号直接入栈,左括号改右括号入栈。
#include<bits/stdc++.h>
using namespace std;
int n,t;
int a[1000010];
stack<int>st;
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)scanf("%d",a+i);
scanf("%d",&t);
for (int i=1;i<=t;i++)
{
int x;
scanf("%d",&x);a[x]*=-1;
}
for (int i=n;i>=1;i--)
{
if (!st.empty()&&st.top()+a[i]==0)st.pop();//栈中只有右括号,如果匹配了这个一定是左括号
else if (a[i]<0)st.push(a[i]);//右括号入栈
else a[i]*=-1,st.push(a[i]);//左括号没有匹配成功就变号也入栈
}
if (!st.empty())puts("NO");
else {puts("YES");for (int i=1;i<=n;i++)printf("%d ",a[i]);}
}
评价:中高档题。
K. Long Jumps by zhber
description:
一个尺子上已经有
n
个刻度,分别是
solution:
a1=0
,所以至多添加两个刻度
x,y
即可量出这两个数。这说明答案不超过
2
,因此判断
评价:由于这个trick,划分到高档题,这题的定位是选手偏后期才会选择完成的。
//by K题一血选手minisam233
#include<cstdio>
#include<iostream>
using namespace std;
int n,l,x,y;
int a[100001];
bool check(int x){
//printf("a%d ",x);
int left=1,right=n,mid,use;
while (left<=right){
mid=(left+right)/2;
if (a[mid]==x) return true;
if (a[mid]<x){
use=mid;
left=mid+1;
}
else right=mid-1;
}
//printf("%d\n",use);
if (x==a[use]) return true;
else return false;
}
int main(){
scanf("%d%d%d%d",&n,&l,&x,&y);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int flag1=0,flag2=0;
for (int i=1;i<=n;i++){
if (a[i]+x<=l){
if (check(a[i]+x)){
flag1=1;
break;
}
}
if (a[i]-x>=0){
if (check(a[i]-x)){
flag1=1;
break;
}
}
}
for (int i=1;i<=n;i++){
if (a[i]+y<=l){
if (check(a[i]+y)){
flag2=1;
break;
}
}
if (a[i]-y>=0){
if (check(a[i]-y)){
flag2=1;
break;
}
}
}
//printf("\n%d %d\n",flag1,flag2);
if (flag1==1 && flag2==1){
printf("0");
return 0;
}
if (flag1==1 && flag2==0){
printf("1\n%d",y);
return 0;
}
if (flag1==0 && flag2==1){
printf("1\n%d",x);
return 0;
}
for (int i=1;i<=n;i++){
if (a[i]+x<=l){
if (a[i]+x+y<=l && check(a[i]+x+y)){
printf("1\n%d",a[i]+x);
return 0;
}
if (a[i]+x-y>=0 && check(a[i]+x-y)){
printf("1\n%d",a[i]+x);
return 0;
}
}
if (a[i]-x>=0){
if (a[i]-x+y<=l && check(a[i]-x+y)){
printf("1\n%d",a[i]-x);
return 0;
}
if (a[i]-x-y>=0 && check(a[i]-x-y)){
printf("1\n%d",a[i]-x);
return 0;
}
}
}
printf("2\n%d %d",x,y);
return 0;
}
L. Stadium and Games
solution:
设
n
个人比赛,
评价:难题。
//by L题一血选手sy742705903
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long LL;
const LL maxxN = 1e18+1;
LL out[100];
int cnnt;
LL maxx;
LL c(LL t1,LL x)
{
return x * (x - 1) / 2 + (t1 - 1) * x;
}
LL judge(LL n, LL t1)
{
LL r,l;
l = 0;
r = maxx;
while(r - l> 1) {
LL mid = (r + l) / 2;
if(c(t1,mid) == n) {
return mid;
} else if(c(t1, mid) > n)
r = mid;
else if(c(t1,mid) < n)
l = mid;
}
maxx = r;
if(c(t1,r) == n)
return r;
else if(c(t1,l) == n)
return l;
else if(r==1 && l == 0)
return 0;
return -1;
}
int main()
{
LL n;
scanf("%I64d",&n);
cnnt = 0;
maxx = sqrt(4 * n);
LL t1 = 1;
while(1) {
LL temp = judge(n, t1);
if(temp == 0)
break;
else if(temp != -1 && temp%2 != 0)
out[cnnt++] = temp * t1;
t1 *= 2;
}
sort(out, out+cnnt);
if(cnnt > 0) {
for(int i=0; i<cnnt; i++) {
if(i>0 && out[i] == out[i-1])
continue;
printf("%I64d\n",out[i]);
}
} else
printf("-1\n");
return 0;
}