蓝桥杯 第十一届软件类校内模拟赛——C/C++程序设计(4月19日)

前言:答案不保证正确!仅供参考!

第一题:

一个 2019 2019 2019的无向连通图,最少的边应该是 n − 1 n-1 n1条,也就是 2018 2018 2018,构成一颗树。

第二题:

12.5 M B 12.5MB 12.5MB 1 M B = 2 20 B 1MB=2^{20}B 1MB=220B,所以也就是 12.5 ∗ 2 20 = 13107200 B 12.5*2^{20}=13107200B 12.5220=13107200B

第三题:

组合数学的一道题目,题目中只有两个 A A A是相等的总共 7 7 7个字符,我们先排 A A A C 7 2 C_{7}^{2} C72另外的是 A 5 5 A_{5}^{5} A55,所以答案是 C 7 2 ∗ A 5 5 = 2520 C_{7}^{2}*A_{5}^{5}=2520 C72A55=2520.
我后面用暴力验证了一下,以下是暴力的代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
inline void out(int x) {
    if (x > 9) out(x / 10);
    putchar(x % 10 + '0');
}
map<string, bool> mp;
int main() {
    int sum = 0;
    int cnt[10] = {0};
    string s = "LANQIAO";
    for (int i = 0; i < 7; i++)
    for (int j = 0; j < 7; j++)
    for (int k = 0; k < 7; k++)
    for (int l = 0; l < 7; l++)
    for (int m = 0; m < 7; m++)
    for (int n = 0; n < 7; n++)
    for (int o = 0; o < 7; o++) {
        memset(cnt, 0, sizeof(cnt));
        cnt[i]++;
        cnt[j]++;
        cnt[k]++;
        cnt[l]++;
        cnt[m]++;
        cnt[n]++;
        cnt[o]++;
        bool flag = false;
        for (int ii = 0; ii < 7; ii++) {
            if (cnt[ii] > 1) flag = true;
        }
        if (flag) continue;
        //cout << s[1] <
        string t = "";
        t += s[i];
        t += s[j];
        t += s[k];
        t += s[l];
        t += s[m];
        t += s[n];
        t += s[o];


        //cout << t << endl;
        if (mp[t] == false) mp[t] = true, sum++;
    }
    cout << sum << endl;
}

第四题:

直接暴力求出 8 8 8个括号的序列有 2 8 2^8 28中可能,所以枚举每种可能,再用栈去判断是否是合法序列。
代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
inline void out(int x) {
    if (x > 9) out(x / 10);
    putchar(x % 10 + '0');
}
int main() {
    int n = 8, sum = 0;
    for (int i = 0; i < (1 << n); i++) {
        string s = "";
        for (int j = 0; j < n; j++) {
            if ((1 << j) & i) s += ')';
            else s += '(';
        }
        //cout << s << endl;
        stack<char> st;
        for (int j = 0; j < s.size(); j++) {
            if (st.empty()) st.push(s[j]);
            else if (s[j] == ')' && st.top() == '(') {
                st.pop();
            } else st.push(s[j]);
        }
        if (st.size() == 0)  {
            cout << s << endl;
            sum++;
        }
    }
    cout << sum << endl;
}

第五题:

用一个数组 c n t cnt cnt(0对应 a a a)去记录每一个对应的字母 + 3 +3 +3% 26 26 26最后的最后的值,然后遍历字符串,最后就有 c n t [ a [ i ] − ′ a ′ ] + ′ a ′ cnt[a[i]-'a']+'a' cnt[a[i]a]+a

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
inline void out(int x) {
    if (x > 9) out(x / 10);
    putchar(x % 10 + '0');
}
int main() {
    char s[110];
    int cnt[50] = {0};
    for (int i = 0; i < 26; i++) {
        cnt[i] = (i + 3) % 26;
    }
    scanf("%s", s);
    int len = strlen(s);
    for (int i = 0; i < len; i++) {
        int x = cnt[s[i] - 'a'];
        char c = x + 'a';
        printf("%c", c);
    }
    return 0;
}

第六题:

题目数据最后到 1 e 6 1e6 1e6,所以暴力就可以解决问题了。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
inline void out(int x) {
    if (x > 9) out(x / 10);
    putchar(x % 10 + '0');
}
int main() {
    int n, a, b, c, sum = 0;
    read(n);
    read(a), read(b), read(c);
    for (int i = 1; i <= n; i++) {
        if (i % a != 0 && i % b != 0 && i % c != 0) sum++;
    }
    out(sum);
    return 0;
}

第七题:

用四个循环写出螺旋矩阵,一下是代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
inline void out(int x) {
    if (x > 9) out(x / 10);
    putchar(x % 10 + '0');
}
int b[1010][1010];
int main() {
	int n, m = 0, t = 0, hang, lie, x, y;
	cin >> n >> m >> x >> y;
    hang = m, lie = n;
	int ci = lie / 2 + lie % 2;
	n = n * m, m = 0;
	for(int i = 0; i < ci; i++){
		for(int j = i; j <= hang - i - 1 && m <= n - 1; j++)
			b[i][j] = m++;
		for(int j = i + 1; j <= lie - i - 2 && m <= n - 1; j++)
			b[j][hang - i - 1] = m++;
		for (int j = hang - i - 1; j >= i && m <= n - 1; j--)
            b[lie - 1 - i][j] = m++;
        for (int j = lie - 2 - i; j >= i + 1 && m <= n - 1; j--)
            b[j][i] = m++;
	}
    out(b[x - 1][y - 1] + 1);
	return 0;
}

第八题:

如果使用 d f s dfs dfs的话,那么复杂度应该是 n m n^m nm,所以连 10 10 10都跑不过去,所以应该是用 d p dp dp解决了,我们可以设 d p i , j dp_{i,j} dpi,j i i i点中的大于\小于 j j j点,那么假如 i i i % 2 = = 0 2 == 0 2==0,这是个偶数点,那么 j j j点可行的方案有 d p i − 1. j + 1 + d p i , j − 1 dp_{i-1.j+1}+dp_{i,j-1} dpi1.j+1+dpi,j1,意思就是之前 i − 1 i-1 i1时比 j j j打的点的数量加上 1 1 1~ j − 1 j-1 j1的方案数,所以就有状态方程 d p i , j = { ( d p i − 1 , j + 1 + d p i , j − 1 ) % m o d i % 2==0 ( d p i − 1 , j − 1 + d p i , j + 1 ) % m o d i % 2==1 dp_{i,j}= \begin{cases} (dp_{i-1,j+1}+dp_{i,j-1})\% mod & \text{i \% 2==0} \\ (dp_{i-1,j-1}+dp_{i,j+1}) \% mod & \text{i \% 2==1} \end{cases} dpi,j={(dpi1,j+1+dpi,j1)%mod(dpi1,j1+dpi,j+1)%modi % 2==0i % 2==1

如果要省空间的话,可以使用滚动数组。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
inline void out(int x) {
    if (x > 9) out(x / 10);
    putchar(x % 10 + '0');
}
const int maxn = 1010;
const int mod = 10000;
int dp[maxn][maxn] = {0};
int main() {
    int m, n;
    read(m), read(n);
    for (int i = 1; i <= n; i++) dp[1][i] = n - i + 1;
    for (int i = 2; i <= m; i++) {
        if (!(i & 1)) {
            for (int j = 1; j <= n; j++) dp[i][j] = (dp[i - 1][j + 1] + dp[i][j - 1]) % mod;
        } else {
            for (int j = n; j >= 1; j--) dp[i][j] = (dp[i - 1][j - 1] + dp[i][j + 1]) % mod;
        }
    }
    if (m & 1) out(dp[m][1]);
    else out(dp[m][n]);
    return 0;
}

滚动数组做法

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
inline void out(int x) {
    if (x > 9) out(x / 10);
    putchar(x % 10 + '0');
}
const int maxn = 1010;
const int mod = 10000;
int dp[2][maxn] = {0};
int main() {
    int m, n, o = 1;
    read(m), read(n);
    for (int i = 1; i <= n; i++) dp[o][i] = n - i + 1;
    o ^= 1;
    for (int i = 2; i <= m; i++) {
        if (!(i & 1)) {
            for (int j = 1; j <= n; j++) dp[o][j] = (dp[o ^ 1][j + 1] + dp[o][j - 1]) % mod;
        } else {
            for (int j = n; j >= 1; j--) dp[o][j] = (dp[o ^ 1][j - 1] + dp[o][j + 1]) % mod;
        }
        o ^= 1;
    }
    if (m & 1) out(dp[o ^ 1][1]);
    else out(dp[o ^ 1][n]);
    return 0;
}

第九题:

感觉是个最小生成树的问题,我们可以将所有的距离都求出来, n n n最大时 1000 1000 1000,所以最多的边的 100 0 2 1000^2 10002,这个范围用最小生成树时可行的,然后就是用 k r u s c a l kruscal kruscal写个模板,(需要注意的是距离的计算公式 h h h在括号外面)。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
inline void out(int x) {
    if (x > 9) out(x / 10);
    putchar(x % 10 + '0');
}
const int maxn = 1e6 + 10;
struct Edge {
    int u;
    int v;
    double dis;
    bool friend operator < (Edge a, Edge b) {
        return a.dis < b.dis;
    }
};
Edge edge[maxn];
double pow2(double x) {return x * x;}
int father[maxn];
int FindFather(int x) {
    int a = x;
    while (father[x] != x) x = father[x];
    while (a != father[a]) {
        int z = a;
        a = father[a];
        father[z] = x;
    }
    return x;
}
void UnionFather(int a, int b) {
    int fa = FindFather(a);
    int fb = FindFather(b);
    if (fa != fb) father[fa] = fb;
}
int main() {
    int n;
    double x[1010], y[1010], h[1010];
    read(n);
    for (int i = 1; i <= n; i++) {
        read(x[i]), read(y[i]), read(h[i]);
    }
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = i + 1; j <= n; j++) {
            edge[cnt].u = i;
            edge[cnt].v = j;
            edge[cnt++].dis = sqrt(pow2(x[i] - x[j]) + pow2(y[i] - y[j])) + pow2(h[i] - h[j]);
        }
    }
    sort(edge, edge + cnt);
    double ans = 0, ccnt;
    for (int i = 0; i <= n; i++) father[i] = i;
    for (int i = 0; i < cnt; i++) {
        if (FindFather(edge[i].u) != FindFather(edge[i].v)) {
            UnionFather(edge[i].u, edge[i].v);
            ans += edge[i].dis;
            ccnt++;
            if (ccnt == n - 1) break;
        }
    }
    printf("%.2lf", ans);
    return 0;
}

第十题:

应该是 d f s dfs dfs解决的,对于每一个 i i i点,我们去判断之前标记过的点和这个点会不会冲突(标记过说明这个点是可用的),如果这个点没有冲突的话,那么就标记这个点并且往下 d f s dfs dfs,复杂度应该是 O ( 2 n ) O(2^n) O(2n) n < = 30 n<=30 n<=30,所以肯定会超时的(写题解的时候突然醒悟了QAQ),所以可以加上剪枝,我们可以设一个后缀和,然后如果加上后缀和的值比最大值来的小,那么就可以直接 r e t u r n return return(个人想法,不知道对错),但是下面的代码还是可以混分的(手动滑稽)。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
    char c;
    int sgn;
    if (c = getchar(), c == EOF) return ;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1:1;
    ret = (c == '-') ? 0:(c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return ;
}
inline void out(int x) {
    if (x > 9) out(x / 10);
    putchar(x % 10 + '0');
}
int Max = 0, n;
int x[50], y[50], r[50];
bool book[50] = {false};
int pow2(int x) {return x * x;}
bool check(int i, int j) {
    if (r[i] + r[j] > sqrt(pow2(x[i] - x[j]) + pow2(y[i] - y[j]))) return false;
    else return true;
}
void dfs(int step, int val) {
    if (step == n) {
        Max = max(Max, val);
        return ;
    }
    for (int i = step; i <= n; i++) {
        bool flag = true;
        for (int j = 0; j < step; j++) {
            if (book[j] && check(i, j) == false) {
                flag = false;
                break;
            }
        }
        if (flag) {
            book[i] = true;
            dfs(i + 1, val + pow2(r[i]));
            book[i] = false;
        }
    }
}
int main() {
    read(n);
    for (int i = 0; i < n; i++) read(x[i]), read(y[i]), read(r[i]);
    dfs(0, 0);
    printf("%d", Max);
    return 0;
}

你可能感兴趣的:(蓝桥杯)