2018广东工业大学校赛

题目连接: https://www.nowcoder.com/acm/contest/90#question

A 跳台阶

  • 题意:有一个n级台阶的楼梯,小明一次可以向上跳1步,两步,甚至是n步,请问小明跳到n级台阶有多少种跳法?

  • 思路:类比于每次只能跳一个台阶或两个台阶,可以很容易的看出\(ans[i] = \sum_{j = 1}^{i}ans[j]\)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
typedef long long ll;
 
char s[maxn];
 
ll ans[50];
 
int main() {
    int n, T;
    scanf("%d", &T);
    while(T--) {
        memset(ans, 0, sizeof ans);
        scanf("%d", &n);
        for(int i = 0; i <= n; i++) ans[i] = 1;
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j < i; j++) { ans[i] += ans[j];  }
        }
        printf("%d\n", ans[n]);
    }
    return 0;
}

B 跳一跳,很简单的

C 平分游戏

  • 题目::共有n位同学,他们都按照编号顺序坐在一个圆桌旁。第i位同学一开始有a[i]个硬币,他们希望使得每位同学手上的硬币变成相同的数目。每一秒钟,有且仅有一位同学可以把自己手上的一枚硬币交给另一位同学,其中这两位同学中间必须间隔k位同学。问最少几秒后所有同学手上的有相同数量的硬币

  • 思路:首先分析座位是相邻的情况:

    • 假设最后每个人有M个硬币,所有人按顺序编号为1,2,3,...,n;
    • 对于第i(i<n)个人,他可以给第(i-1)个人\(x_{i+1}\)枚硬币,这里如果是第(i+1)个人给他,则\(x_{i+1}\)记为负数;同时,第(i+1)个人也可以给他\(x_{i}\)枚硬币,那么对于这个人,我们可以得到一个方程\(A_i - x_i + x_{i+1} = M\),同样,对于其他人我们也可以得到这样的方程;最后我们可以得到n个方程,但是很遗憾,对于第n个人,\(A_n-x_n+x_1=M\)是个多余的方程, 我们可以通过前n-1个方程把它推出来;
    • 分析前n-1个方程, 对于第一个\(A_1 -x_1+x_2=M => x_2 = M - A_1+x_1 = x_1-C_1\);对于剩下的n-2个方程,我们也可以得出类似的式子,那么题目要求的最小值就变成了求\(|x_1| + |x_1-C_1|+...+|x_1-C_{n-1}|\)的最小值,这里\(|x_1-C_i|\)即为数轴上点\(x_1\)到其他点的距离,直接取中位数就可以了。

然后是不相邻的情况:我们只需对每个人,找出它后面的人的硬币数,然后重新将他们放在一个数组里即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
int a[maxn], vis[maxn];
ll C[maxn];
vector<int> v;
int main() {
    int k, n;
    while(~scanf("%d %d", &n, &k)) {
        ll sum = 0;
        for(int i = 0; i < n; i++) { scanf("%d", &a[i]); sum += a[i]; }
        if(sum % n) { printf("gg\n"); continue; }
        if(!sum) { printf("0\n"); continue; }
        if(k >= n - 1) {
            int fl = 0;
            for(int i = 1; i < n; i++) if(a[i] != a[0]) fl = 1;
            if(fl) printf("gg\n");
            else printf("0\n");
            continue;
        }
        ll M = sum / n, ans = 0;
        int fl = 1;
        memset(vis, 0, sizeof vis);
        for(int i = 0; i < n; i++) {
            int ind = i, cnt = 0;
            ll tmp = 0;
            if(vis[ind]) continue;
            while(!vis[ind]) {
                v.push_back(a[ind]);
                cnt++;
                vis[ind] = 1;
                tmp += a[ind];
                ind = (ind + k + 1) % n;
            }
            if(cnt * M != tmp) { fl = 0; break; }
            C[0] = 0;
            for(int j = 1; j < v.size(); j++) C[j] = C[j - 1] + v[j] - M;
            sort(C, C + v.size());
            ll x1 = C[v.size() / 2];
            for(int j = 0; j < v.size(); j++) ans += abs(x1 - C[j]);
            v.clear();
        }
        if(!fl) printf("gg\n");
        else printf("%lld\n", ans);
    }
    return 0;
}

D psd面试

  • 题目:
  • 思路:
    • 这题可以直接用动态规划写
    • 对于区间(i, j),如果\(s[i] == s[j]\),那么有\(dp[i][j] = dp[i+1][j-1]+2\), 如果\(s[i] != s[j]\), 那么有\(dp[i][j] = max(dp[i+1][j], dp[i][j-1])\);然后直接记忆化搜索一下就好,复杂度\(O(n^2)\)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1300;
typedef long long ll;
int n;
char s[maxn];
int dp[maxn][maxn];
 
int lsp(int i, int j) {
    if(i == j) return 1;
    if(i > j) return 0;
    if(dp[i][j]) return dp[i][j];
    if(s[i] == s[j]) return dp[i][j] = lsp(i + 1, j - 1) + 2;
    return dp[i][j] = max(lsp(i, j - 1), lsp(i + 1, j));
}
 
int main() {
    while(~scanf("%s", s)) {
        n = strlen(s);
        for(int i = 0; i < n; i++) {
            if(s[i] >= 'A' && s[i] <= 'Z') s[i] = s[i] - 'A' + 'a';
        }
        memset(dp, 0, sizeof dp);
        printf("%d\n", n - lsp(0, n - 1));
    }
    return 0;
}

E 回旋星空

  • 题目:计算回旋图标的个数,即选中三颗星星,分别作为回旋图标的起点,拐点和终点,假设现在有三个星星分别为i,j,k,如果d(a[i],a[j]) == d(a[j],a[k])则表示找到了一个回旋图标,其中d(x,y)表示这两个点的欧氏距离为了给它很大的希望(i,j,k)和(k,j,i)被认为是两个不同的回旋图标.

  • 思路:对于每个点,暴力它到其他点的距离,如果有n(n>=2)个相同距离的点, 那个ans+=n*(n-1)/2即可

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
typedef long long ll;
double EPS = 1e-10;
struct P{
    int x, y;
    P() {}
    P(int x, int y): x(x), y(y) {}
} p[1005];
map<ll, int> mp;
int main() {
    int T;
    int n, m;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for(int i = 0; i < n; i++) {
            scanf("%d %d", &p[i].x, &p[i].y);
        }
        ll ans = 0;
        for(int i = 0; i < n; i++) {
            mp.clear();
            for(int j = 0; j < n; j++) {
                ll len = (p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y);
                mp[len]++;
            }
            map<ll, int>::iterator it;
            for(it = mp.begin(); it != mp.end(); it++) {
                if(it -> second < 2) continue;
                ans += 1LL * (it -> second - 1) * it -> second;
            }
        }
        if(!ans) printf("WA\n");
        else printf("%lld\n", ans);
    }
    return 0;
}

F 等式

  • 题意:

  • 思路:

#include<bits/stdc++.h>
using namespace std;
char s[1500];
int main() {
    int T, n;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        int ans = 1;
        for(int i = 2; i * i <= n; i++) {
            int num = 0;
            while(n % i == 0) { n /= i; num++; }
            ans = ans * (num << 1 | 1);
            if(n == 1) break;
        }
        if(n > 1) ans *= 3;
        printf("%d\n", (ans >> 1) + 1);
    }
    return 0;
}

G 旋转矩阵

  • 题意:

  • 思路:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
typedef long long ll;
double EPS = 1e-10;
 
char s[50][50];
char op[maxn];
 
int main() {
    int T;
    int n, m;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d", &n, &m);
        for(int i = 0; i < n; i++) scanf("%s", s[i]);
        scanf("%s", op);
        int len = strlen(op), cnl = 0, cnr = 0;
        for(int i = 0; i < len; i++) {
            if(op[i] == 'L') cnl++;
            if(op[i] == 'R') cnr++;
        }
        cnl %= 4;
        cnr %= 4;
//        printf("cnl = %d cnr = %d\n", cnl, cnr);
        if(cnl == cnr) {
            printf("%d %d\n", n, m);
            for(int i = 0; i < n; i++) printf("%s\n", s[i]);
        } else if(cnl - cnr == 2 || cnr - cnl == 2) {
            printf("%d %d\n", n, m);
            for(int i = n - 1; i >= 0; i--) {
                for(int j = m -1; j >= 0; j--) printf("%c", s[i][j]);
                printf("\n");
            }
 
 
        } else if(cnl - cnr == 1 || cnr - cnl == 3) {
            printf("%d %d\n", m, n);
            int cnt = 0;
            for(int j = m- 1; j >= 0; j--) {
                for(int i = 0; i < n; i++) {
                    if(s[i][j] == '-') printf("|");
                    else if(s[i][j] == '|') printf("-");
                    else printf("%c", s[i][j]);
                }
                printf("\n");
            }
        } else if(cnl - cnr == 3 || cnr - cnl == 1) {
            printf("%d %d\n", m, n);
            for(int j = 0; j < m; j++) {
                for(int i = n - 1; i >= 0; i--) {
                    if(s[i][j] == '-') printf("|");
                    else if(s[i][j] == '|') printf("-");
                    else printf("%c", s[i][j]);
                }
                printf("\n");
            }
        }
        printf("\n");
    }
    return 0;
}

H 哲哲的疑惑


I 填空题

  • 题意:

  • 思路:输出"ac"即可

#include<bits/stdc++.h>
using namespace std;
 
int main() {
    int n, T;
    printf("ac\n");
    return 0;
}

J 强迫症的序列

  • 题意:

  • 思路:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
typedef long long ll;
 
char s[maxn];
 
ll ans[50];
int a[maxn];
 
int main() {
    int n, T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        int mx = 1000000;
        ll ans = 0, sum = 0;
        for(int i = 0; i < n; i++) { scanf("%d", &a[i]);  mx = min(mx, a[i]); sum += a[i]; }
        for(int i = 0; i < n; i++) ans += a[i] - mx;
        printf("%lld %lld\n", ans, (sum + ans * (n - 1)) / n);
    }
    return 0;
}

K 密码

  • 题意:

  • 思路:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
typedef long long ll;
double EPS = 1e-10;
 
char s[50][50];
char op[maxn];
vector<int> v;
 
int main() {
    int T;
    int n, m;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        scanf("%s", op);
        v.clear();
        if(n == 1) {
            printf("%s\n", op);
            continue;
        }
        int d = 2*(n-1), len = strlen(op);
        for(int i = 0; ; i++) {
            v.push_back(d * i);
            if(d * i > len) break;
        }
//        printf("d = %d\n", d);
        for(int i = 0; i < v.size(); i++) if(v[i] < len) printf("%c", op[v[i]]);
        for(int i = 0; i < n - 2; i++) {
            for(int j = 0; j < v.size(); j++) {
                int ind = v[j] + (i + 1), inds = v[j] - (i + 1);
 
                if(inds < len && inds >= 0) printf("%c", op[inds]);
                if(ind < len && ind >= 0) printf("%c", op[ind]);
            }
        }
        for(int i = 0; i < v.size(); i++) if(v[i] + n - 1 < len) printf("%c", op[v[i] + n- 1]);
        printf("\n");
    }
    return 0;
}

L 用来作弊的药水

  • 题意:

  • 思路:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
typedef long long ll;
  
char s[maxn];
  
ll ans[50];
int p[maxn], vis[maxn];
ll x, a, y, b;
int cnt = 0;
  
void init() {
    int m = sqrt(maxn + 0.5);
    for(int i = 2; i <= m; i++) {
        if(!vis[i]) {
            for(int j = i * i; j < maxn; j += i)
                vis[j] = 1;
        }
    }
    for(int i = 2; i < maxn; i++) {
        if(!vis[i]) p[cnt++] = i;
    }
}
  
int p1[maxn/10], p2[maxn/10];
  
int main() {
    int n, T;
    init();
//    for(int i = 0; i < 10; i++) printf("%d ", p[i]);
//    printf("%d\n", cnt);
    scanf("%d", &T);
    while(T--) {
        scanf("%lld %lld %lld %lld", &x, &a, &y, &b);
        memset(p1, 0, sizeof p1);
        memset(p2, 0, sizeof p2);
        for(int i = 0; i < cnt; i++) {
            while(x % p[i] == 0) { p1[i]++; x /= p[i]; }
        }
        for(int i = 0; i < cnt; i++) {
            while(y % p[i] == 0) { p2[i]++; y /= p[i]; }
        }
        int fl = 1;
        if(x != y) fl = 0;
        if(x == y && x != 1 && a != b) fl = 0;
//        printf("x = %lld y = %lld\n", x, y);
        for(int i = 0; i < cnt; i++) {
            if(a * p1[i] != b * p2[i]) { fl = 0; break; }
        }
        if(fl) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
posted @ 2018-03-25 22:42  .ini  阅读(894)  评论(0编辑  收藏  举报