2020.10.17蓝桥杯B组省赛补题

凉了

门牌制作

答案:624

既约分数

#include<iostream>
#include<cstring>

using namespace std;

int gcd(int a, int b){
    return b ? gcd(b, a % b) : a;
}

int main(){
    int res = 0;
    for(int i = 1; i <= 2020; i ++)
        for(int j = 1; j <= 2020; j ++)
            if(gcd(i, j) == 1) res ++;
    
    cout << res;
}

答案:2481215

蛇形填数

#include<iostream>
using namespace std;

const int N = 50;

int g[N][N];

int main(){
    int k = 1;
    
    int m = 1, n = 1;
    
    while(g[20][20] == 0)
        if(m == 1){
            g[m][n ++] = k ++;
            while(n > 1) g[m ++][n --] = k ++;
        }else if(n == 1){
            g[m ++][n] = k ++;
            while(m > 1) g[m --][n ++] = k ++;
        }
    
    cout << g[20][20];
    
    return 0;
}

答案: 761

跑步

#include<iostream>
using namespace std;

int main(){
    int y = 2000, m = 1, d = 1;
    int w = 6; // saturday
    
    int res = 0;
    
    while(y != 2020 || m != 10 || d != 1){
        if(w == 1 || d == 1) res += 2;
        else res ++;
        d ++;
        w = (w + 1) % 7;
        int t;
        if(m == 4 || m == 6 || m == 9 || m == 11) t = 30;
        else if(m != 2) t = 31;
        else if(y % 4 == 0 && y % 100 || y % 400 == 0) t = 29;
        else t = 28;
        
        if(d > t) d = 1, m ++;
        if(m > 12) m = 1, y ++;
    }
    
    cout << res + 2;
}

答案:8879

七段码

#include<iostream>
#include<vector>

using namespace std;

const int N = 7;

char t[N] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
vector<char> res;
int p[N];
int cnt;

int get(int a, int b){
    if(a == 'a') return b == 'f' || b == 'b';
    if(a == 'b') return b == 'a' || b == 'g' || b == 'c';
    if(a == 'c') return b == 'b' || b == 'g' || b == 'd';
    if(a == 'd') return b == 'e' || b == 'c';
    if(a == 'e') return b == 'g' || b == 'f' || b == 'd';
    if(a == 'f') return b == 'g' || b == 'e' || b == 'a';
    if(a == 'g') return b == 'f' || b == 'e' || b == 'b' || b == 'c';
}

int find(int x){
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int check(){
    int len = res.size();
    
    for(int i = 0; i < len; i ++) p[i] = i;
    
    for(int i = 0; i < len; i ++)
        for(int j = i + 1; j < len; j ++){
            int a = find(i), b = find(j);
            if(get(res[i], res[j])) p[b] = a;
        }
        
    int ans = 0;
    
    for(int i = 0; i < len; i ++) 
        if(p[i] == i) ans ++;
    
    return ans == 1;
}

void dfs(int u){
    if(res.size()){
        for(auto i : res) cout << i << ' ';
        cout << endl;
        if(check()) cnt ++;
    }
    
    for(int i = u; i < 7; i ++){
        res.push_back(t[i]);
        dfs(i + 1);
        res.pop_back();
    }
}

int main(){
    
    dfs(0);
        
    cout << cnt;
}

答案:80

成绩统计

#include<iostream>
using namespace std;

const int N = 10010;

int n;
int _60, _85;

int round(double x){
    return (int(x * 10) + 5) / 10; 
}

int main(){
    cin >> n;
    
    for(int i = 0; i < n; i ++){
        int x;
        cin >> x;
        
        if(x >= 60) _60 ++;
        if(x >= 85) _85 ++;
    }
    
    _60 = round((double) _60 * 100 / n);
    _85 = round((double) _85 * 100 / n);
    
    printf("%d%%
", _60);
    printf("%d%%", _85);
}

回文日期

最大日期差2921940,按天枚举应该不会超时

#include<iostream>
#include<sstream>

using namespace std;

int get(int y, int m){
    if(m == 4 || m == 6 || m == 9 || m == 11) return 30;
    else if(m != 2) return 31;
    else if(y % 4 == 0 && y % 100 || y % 400 == 0) return 29;
    else return 28;
}

int check(int date){
    stringstream ss;
    ss << date;
    
    string t;
    ss >> t;
    
    int l = 0, r = t.size() - 1;
    while(l < r){
        if(t[l] != t[r]) return 0;
        l ++, r --;
    }
    
    return 1;
}

int main(){
    int date;
    
    cin >> date;
    
    int y = date / 10000, m = date / 10000 / 100, d = date / 10000 % 100;
    
    int backup = date;
    
    do{
        d ++;
        int t = get(y, m);
        if(d > t) d = 1, m ++;
        if(m > 12) m = 1, y ++;
        date = y * 10000 + m * 100 + d;
    }while(!check(date));
    
    cout << date << endl;
    
    date = backup;
    y = date / 10000, m = date / 10000 / 100, d = date / 10000 % 100;
    
    do{
        d ++;
        int t = get(y, m);
        if(d > t) d = 1, m ++;
        if(m > 12) m = 1, y ++;
        date = y * 10000 + m * 100 + d;
    }while(!check(date) || date / 10000 % 100 != date / 10000 / 100);
    
    cout << date << endl;
    
    return 0;
}

子串分值和

最多60分。。。

#include<iostream>
#include<cstring>

using namespace std;

#define LL long long

const int N = 100010;

char s[N];
int st[26];
int n;
int res;

int main(){
    cin >> s + 1;
    
    for(int i = 1; s[i]; i ++){
        LL cnt = 0;
        for(int j = i; s[j]; j ++){
            st[s[j] - 'a'] ++;
            if(st[s[j] - 'a'] == 1) cnt ++;
            res += cnt;
        }
        memset(st, 0, sizeof st);
    }
    
    cout << res;
    
    return 0;
}

上大佬的递推做法
2020.10.17蓝桥杯B组省赛补题
其中last[i]表示对于i(1~n)号位置的s[i]上一个和他相等的位置。
(O(n))完美!

#include<iostream>
#include<cstring>

using namespace std;

const int N = 100010;

int f[N];
int p[26], last[N];
char s[N];

// f[i] = f[i - 1] + i - last[i]
// last[i]表示和s[i]相等的上一个位置

// a    b   a   b   c
// 0    0   1   2   0


/*
以c为结尾 = 以b为结尾的 + 5 - 0

c
bc
abc
babc
ababc

7 + 5 = 1 + 2 + 3 + 3 + 3 = 12

以b为结尾的 = 以a为结尾的 + 4 - 2

b
ab
bab
abab

5 + 2 = 7

以a为结尾的 = 以b为结尾的 + 3 - 1

a
ba
aba

3 + 2 = 5

以b为结尾的 = 以a为结尾的 + 2 - 0

b
ab

3

以a为结尾的 = 以a为结尾的 + 1 - 0

a

1

*/

int main(){
    cin >> s + 1;
    
    memset(p, -1, sizeof p);
    
    for(int i = 1; s[i]; i ++){
        if(p[s[i] - 'a'] == -1) p[s[i] - 'a'] = i;
        else{
            int a = p[s[i] - 'a'];
            last[i] = a;
            p[s[i] - 'a'] = i;
        }
    }
    
    for(int i = 1; s[i]; i ++)
        f[i] += f[i - 1] + i - last[i];
    
    int res = 0;
    for(int i = 1; s[i]; i ++) res += f[i];
    
    cout << res;
        
    return 0;
}

平面切分

没写

字串排序

打了个20的表

蹲一波大佬的题解