1. 组队
2. 年号字串
#include
#include
#include
#include
using namespace std;
char ans[10];
int main(){
ans[0] = 'A';
for(int i = 2; i <= 2019; i++){
if(ans[0] == 'Z'){
if(ans[1] == '\0') ans[1] = 'A';
else if(ans[1] == 'Z'){
if(ans[2] == '\0') ans[2] = 'A';
else ans[2]++;
ans[1] = 'A';
}
else ans[1]++;
ans[0] = 'A';
}
else ans[0]++;
reverse(ans, ans + strlen(ans));
cout << ans << endl;
reverse(ans, ans + strlen(ans));
}
reverse(ans, ans + strlen(ans));
cout << ans << endl;
return 0;
}
3. 数列求和
#include
#include
#include
#include
using namespace std;
const int mod = 10000;
int a, b, c, d;
int main(){
b = 1;
c = 1;
d = 3;
for(int i = 5; i <= 20190324; i++){
a = b + c + d;
b = c % mod;
c = d % mod;
d = a % mod;
a = a % mod;
}
cout << a << endl;
return 0;
}
4. 数的分解
答案 40785
思路 直接枚举, 时间复杂度是9次方,大概10秒可以算出来,完全没问题,因为存在重复abc, acb, cab, cba, bac, bca,结果除以6就可以了
#include
#include
#include
#include
using namespace std;
int ans;
bool check(int n){
while(n){
if(n % 10 == 2 || n % 10 == 4) return false;
n /= 10;
}
return true;
}
int main(){
for(int i = 1; i < 2019; i++)
for(int j = 1; j < 2019; j++)
for(int k = 1; k < 2019; k++){
if(i + j + k == 2019){
if(check(i) && check(j) && check(k)){
if(i != j && i != k && j != k)ans++;
}
}
}
cout << ans / 6 << endl;
return 0;
}
5. 迷宫
思路 用bfs, 结构体内存下路径,每次按照最小的字典序走,第一次走到终点对应的路径就是最小的字典序。
答案 DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR
代码
#include
#include
#include
#include
#include
using namespace std;
const int n = 30, m = 50;
struct node{
int x, y, sum;
char p[500];
};
char map[35][55];
bool vis[35][55];
char path[200];
int dx[] = {1, 0, 0, -1};
int dy[] = {0, -1, 1, 0};
char p[] = {'D', 'L', 'R', 'U'};
void bfs(){
queue<node> q;
q.push({1, 1, 1});
while(q.size()){
node t = q.front();
q.pop();
int x = t.x;
int y = t.y;
int s = t.sum;
if(vis[x][y]) continue;
vis[x][y] = true;
for(int i = 0; i < 4; i++){
int fx = x + dx[i];
int fy = y + dy[i];
if(fx > 0 && fx <= n && fy > 0 && fy <= m && map[fx][fy] == '0' && !vis[fx][fy]){
t.p[s] = p[i];
if(fx == n && fy == m){
for(int i = 1; i <= s; i++) cout << t.p[i];
cout << s << endl;
}
node te;
te.x = fx, te.y = fy, te.sum = s + 1;
memcpy(te.p, t.p, sizeof t.p);
q.push(te);
}
}
}
}
int main(){
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
cin >> map[i][j];
bfs();
return 0;
}
6. 特别数的和
思路
直接暴力,数据最大是10000,所以运算最大也是40000,题目给了1s,所以应该是可以过的
#include
#include
#include
#include
using namespace std;
int ans;
bool check(int n){
while(n){
if(n % 10 == 2 || n % 10 == 0 || n % 10 == 1 || n % 10 == 9)
return true;
n /= 10;
}
return false;
}
int n;
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++){
if(check(i)) ans += i;
}
printf("%d\n", ans);
return 0;
}
7. 完全二叉树的权值
思路
就把每层的存起来,遍历一遍找到最大值。
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
ll sum[20];
int a, n;
int getdeep(int n){
int ans = 0;
while(n){
ans++;
n /= 2;
}
return ans;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &a);
sum[getdeep(i)] += a;
}
ll ans = -0x3f3f3f3f;
int deep;
for(int i = 1; i <= 18; i++){
if(sum[i] > ans){
deep = i;
ans = sum[i];
}
}
printf("%d\n", deep);
return 0;
}
8. 等差数列
思路
等差数列的公差就是给出数列的所有的差的最大公约数
#include
#include
#include
#include
#include
using namespace std;
const int N = 100010;
bool vis[N];
int a[N], b;
int n;
int cnt;
int gcd(int a, int b){
if(b == 0) return a;
return gcd(b, a % b);
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &b);
if(vis[b]) continue;
vis[b] = true;
a[cnt++] = b;
}
n = cnt;
sort(a, a + n);
b = a[1] - a[0];
for(int i = 2; i < n; i++){
int x = a[i] - a[1];
b = gcd(x, b);
}
b = (a[n - 1] - a[0]) / b + 1;
printf("%d\n", b);
return 0;
}
9. 后缀表达式
这道题比较有争议,我用的贪心,有m个减号,就相当于把m个负数变成正数,如果负数不足m个,就把最小的那几个数变成负数,然后相加。
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 100010;
int a[N];
int n, m;
bool cmp(int a, int b){
return abs(a) > abs(b);
}
int main(){
scanf("%d%d", &n, &m);
int s = n + m + 1;
for(int i = 0; i < s; i++){
scanf("%d", a + i);
}
sort(a, a + s, cmp);
for(int i = 0; i < s && m > 0; i++)
if(a[i] < 0) m--, a[i] = -a[i];
if(m > 0){
for(int i = s - 1; i >= 0 && m > 0; i--){
a[i] = -a[i];
m--;
}
}
ll ans = 0;
for(int i = 0; i < s; i++){
ans += a[i];
cout << a[i] << " ";
}
cout << endl;
printf("%lld\n", ans);
return 0;
}
10. 灵能传输
思路
当三个数同号时,不需要操作,,需要操作的时候必须满足一下情况,flag记录还有没有满足交换的情况,有就继续遍历,没有就退出循环。
#include
#include
#include
#include
using namespace std;
const int N = 10010;
int a[N];
int n, t;
bool dif(int a, int b){
if(a > 0 && b < 0) return true;
if(a < 0 && b > 0) return true;
return false;
}
bool Same(int x, int y){
if(x > 0 && y > 0) return true;
if(x < 0 && y < 0) return true;
return false;
}
void sove(int i){
a[i - 1] += a[i];
a[i + 1] += a[i];
a[i] -= 2 * a[i];
}
int main(){
scanf("%d", &t);
while(t--){
scanf("%d", &n);
bool zheng = false, fu = false;
for(int i = 1; i <= n; i++){
scanf("%d", a + i);
if(a[i] > 0) zheng = true;
if(a[i] < 0) fu = true;
}
if(zheng && fu){
bool flag = false;
do{
flag = false;
for(int i = 2; i <= n - 1; i++){
//1
if(a[i] > 0 && dif(a[i + 1], a[i - 1])){
if(a[i - 1] < 0 && abs(a[i - 1]) > a[i] + a[i + 1]){
sove(i);flag = true;
}
else if(a[i - 1] > 0 && abs(a[i + 1]) > a[i] + a[i - 1]){
sove(i);flag = true;
}
}
//2
if(a[i] < 0 && dif(a[i + 1], a[i - 1])){
if(a[i - 1] > 0 && a[i - 1] > abs(a[i] + a[i + 1])){
sove(i);flag = true;
}
if(a[i - 1] < 0 && a[i + 1] > abs(a[i] + a[i - 1])){
sove(i);flag = true;
}
}
//3
if(Same(a[i - 1], a[i + 1]) && dif(a[i], a[i - 1]) && dif(a[i], a[i + 1])){
if(a[i] < 0){
if(a[i - 1] > abs(a[i] || a[i + 1] > abs(a[i]))){
sove(i);flag = true;
}
}
if(a[i] > 0){
if(abs(a[i - 1]) > a[i] || abs(a[i + 1]) > a[i]){
sove(i);flag = true;
}
}
}
}
}while(flag);
}
int ans = -0x3f3f3f3f;
for(int i = 1; i <= n; i++) ans = max(ans, abs(a[i]));
printf("%d\n", ans);
}
return 0;
}