A】
分析:只要判断是否是首尾均为奇数且长度也为奇数即可
不过我是使用构造的方法也可以过
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
int num[105];
int main()
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; ++i)
scanf("%d", &num[i]);
int cnt = 0;
int ok = 1;
for(int i = 0; i < n; ++i)
{
if(num[i] % 2 == 1)
{
int j = i;
for(; j < n; j += 2)
{
if((num[j] % 2 == 1) && (j + 1 >= n || num[j + 1] % 2 == 1))
break;
}
if(j >= n)
{
if(num[n - 1] % 2 == 0)
ok = 0;
if((n - i) % 2 != 0)
cnt += 1;
break;
}
cnt += 1;
i = j;
}
else
{
ok = 0;
break;
}
}
if(cnt % 2 == 0) ok = 0;
if(ok)
printf("Yes\n");
else printf("No\n");
return 0;
}
B】
分析:枚举12,13,23三种情况看是否有一种情况满足条件即可,很好证明
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
int num[1005];
bool used[1005];
int n;
int gcd(int n, int m)
{
if(n % m == 0) return m;
return gcd(m, n % m);
}
void solve(int a, int b)
{
int x = b - a;
int y = num[b] - num[a];
if(x != 0 && y != 0)
{
int g = gcd(abs(x), abs(y));
x /= g;
y /= g;
}
for(int i = 0; i < n; ++i)
{
if(used[i]) continue;
if(i == a || i == b) continue;
int tx = i - a;
int ty = num[i] - num[a];
if(tx != 0 && ty != 0)
{
int tg = gcd(abs(tx), abs(ty));
tx /= tg;
ty /= tg;
if(tx < 0 && ty < 0)
tx = -tx, ty = -ty;
}
else
{
if(y == 0) used[i] = true;
continue;
}
if((x == tx && y == ty) || (x == -tx && y == -ty))
used[i] = true;
}
return;
}
int main()
{
int point;
scanf("%d", &n);
for(int i = 0; i < n; ++i)
scanf("%d", &num[i]);
memset(used, 0, sizeof(used));
used[1] = used[2] = true;
solve(1, 2);
int ok = 1;
for(int i = 3; i < n; ++i)
{
if(!used[i])
{
ok = 0;
break;
}
}
if(ok == 1 && !used[0])
{
printf("Yes\n");
return 0;
}
memset(used, 0, sizeof(used));
used[0] = used[1] = true;
solve(0, 1);
int x = 1;
int y = num[1] - num[0];
int a = -1, b = -1;
for(int i = 0; i < n; ++i)
{
if(!used[i])
{
if(a == -1) a = i;
else b = i;
if(b != -1) break;
}
}
point = a;
ok = 1;
if(a == -1)
{
printf("No\n");
return 0;
}
else if(b == -1)
{
printf("Yes\n");
return 0;
}
else
{
int tx = b - a;
int ty = num[b] - num[a];
if(ty % tx != 0 || ty / tx != y)
{
ok = 0;
}
if(ok)
{
used[a] = used[b] = true;
solve(a, b);
for(int i = 0; i < n; ++i)
{
if(!used[i])
{
ok = 0;
break;
}
}
}
}
if(ok)
{
printf("Yes\n");
return 0;
}
memset(used, 0, sizeof(used));
x = point;
y = num[point] - num[0];
if(y != 0)
{
int g = gcd(x, abs(y));
x /= g;
y /= g;
}
used[0] = used[point] = 1;
solve(0, point);
a = -1, b = -1;
for(int i = 0; i < n; ++i)
{
if(!used[i])
{
if(a == -1) a = i;
else b = i;
if(b != -1) break;
}
}
ok = 1;
if(a == -1)
{
printf("No\n");
return 0;
}
else if(b == -1)
{
printf("Yes\n");
return 0;
}
else
{
int tx = b - a;
int ty = num[b] - num[a];
if(ty != 0)
{
int g = gcd(tx, abs(ty));
tx /= g;
ty /= g;
if((x == tx && y == ty) || (x == -tx && y == -ty))
ok = 1;
else ok = 0;
}
else
{
if(y != 0) ok = 0;
}
if(ok)
{
used[a] = used[b] = true;
solve(a, b);
for(int i = 0; i < n; ++i)
{
if(!used[i])
{
ok = 0;
break;
}
}
}
}
if(ok)
{
printf("Yes\n");
return 0;
}
memset(used, 0, sizeof(used));
x = point - 1;
y = num[point] - num[1];
if(y != 0)
{
int g = gcd(x, abs(y));
x /= g;
y /= g;
}
used[1] = used[point] = 1;
solve(1, point);
a = -1, b = -1;
for(int i = 0; i < n; ++i)
{
if(!used[i])
{
if(a == -1) a = i;
else b = i;
if(b != -1) break;
}
}
ok = 1;
if(a == -1)
{
printf("No\n");
return 0;
}
else if(b == -1)
{
printf("Yes\n");
return 0;
}
else
{
int tx = b - a;
int ty = num[b] - num[a];
if(ty != 0)
{
int g = gcd(tx, abs(ty));
tx /= g;
ty /= g;
if((x == tx && y == ty) || (x == -tx && y == -ty))
ok = 1;
else ok = 0;
}
else
{
if(y != 0) ok = 0;
}
if(ok)
{
used[a] = used[b] = true;
solve(a, b);
for(int i = 0; i < n; ++i)
{
if(!used[i])
{
ok = 0;
break;
}
}
}
}
if(ok)
{
printf("Yes\n");
}
else printf("No\n");
return 0;
}
C】
分析:注意不同字母之间相互独立不会有加和产生,而n个相同的字符合并的和是n*(n -1) / 2,问题转化为确定k由哪些n*(n - 1) / 2构成即可,使用二分查找即可,一直找小于等于k最大的数,然后把k减掉这个数在继续寻找直到k为0
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
int num[1005];
char str[100005];
int main()
{
for(int i = 1; i <= 1000; ++i)
num[i] = i * (i - 1) / 2;
int n;
scanf("%d", &n);
if(n == 0)
{
printf("ab\n");
return 0;
}
int cnt = 0;
int tag = 0;
while(n)
{
int pos = lower_bound(num, num + 1000, n) - num;
while(num[pos] > n) pos -= 1;
n -= num[pos];
for(int i = 0; i < pos; ++i)
str[cnt++] = tag + 'a';
tag += 1;
}
str[cnt] = 0;
printf("%s\n", str);
return 0;
}
D】
分析:这道题注意两个重要的信息就可以了:
1.只有p - t相等的点才会发生碰撞
2.在最左上方的点在碰撞后也是在最左上方
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 1e5 + 5;
struct point
{
int g, p, t, tag;
bool operator < (const point& ano) const
{
if(g != ano.g) return g > ano.g;
if(g == 1) return p < ano.p;
return p > ano.p;
}
}ps[MAXN];
struct node
{
int x, y;
bool operator < (const node& ano) const
{
if(x != ano.x) return x < ano.x;
return y > ano.y;
}
};
vector<int> cof[2 * MAXN];
int res[MAXN][2];
int main()
{
int n, w, h;
scanf("%d%d%d", &n, &w, &h);
for(int i = 0; i < n; ++i)
{
ps[i].tag = i;
scanf("%d%d%d", &ps[i].g, &ps[i].p, &ps[i].t);
cof[ps[i].p - ps[i].t + 100000].push_back(i);
}
for(int i = 0; i <= 200000; ++i)
{
int lim = cof[i].size();
if(lim == 0) continue;
vector<point> vp;
vector<node> vec;
for(int j = 0; j < lim; ++j)
{
int tmp = cof[i][j];
vp.push_back(ps[tmp]);
int x = ps[tmp].g == 1 ? ps[tmp].p : w;
int y = ps[tmp].g == 1 ? h : ps[tmp].p;
vec.push_back((node){x, y});
}
sort(vp.begin(), vp.end());
sort(vec.begin(), vec.end());
for(int j = 0; j < lim; ++j)
{
res[vp[j].tag][0] = vec[j].x;
res[vp[j].tag][1] = vec[j].y;
}
}
for(int i = 0; i < n; ++i)
printf("%d %d\n", res[i][0], res[i][1]);
return 0;
}