2020-06 CSP真题

2020-06 CSP真题

1. 线性分类器

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define db double
#define VI vector<int>
#define PII pair<int, int>
const db Pi = 3.141592653589793;
const int INF = 0x7fffffff;
const int N = 1e3 + 5;
const db eps = 1e-10;
int n, m, x[N], y[N], Alow, Blow, Ahigh, Bhigh, a, b, c;
char type[N];
bool check(int x0, int y0){
    if(c == 0){
        if(b * x0 + a < 0) return 0;
        else return 1;
    }
    else{
        if(-1 * (a + b * x0) > c * y0) return 0;
        else return 1;
    }
}
int main(){
    cin >> n >> m;
    rep(i, 1, n) cin >> x[i] >> y[i] >> type[i];
    rep(j, 1, m){
        cin >> a >> b >> c;
        Alow = Blow = Ahigh = Bhigh = 0;
        rep(i, 1, n){
            if(check(x[i], y[i])) type[i] == 'A' ? Ahigh++ : Bhigh++;
            else type[i] == 'A' ? Alow++ : Blow++;
        }
        if((Ahigh == 0 && Blow == 0) || (Alow == 0 && Bhigh == 0)) puts("Yes");
        else puts("No");
    }
}

2. 稀疏向量

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define db double
#define VI vector<int>
#define PII pair<int, int>
const db Pi = 3.141592653589793;
const int INF = 0x7fffffff;
const int N = 1e5 + 5;
const db eps = 1e-10;
int n, A, B, num, val;
ll sum;
map<int, ll> amp, bmp;
set<int> ast, bst, inter;
set<int>::iterator iter;
int main(){
    cin >> n >> A >> B;
    rep(i, 1, A){
        cin >> num >> val;
        amp.insert({num, val});
        ast.insert(num);
    }
    rep(i, 1, B){
        cin >> num >> val;
        bmp.insert({num, val});
        bst.insert(num);
    }
    set_intersection(ast.begin(), ast.end(), bst.begin(), bst.end(), inserter(inter, inter.begin()));
    sum = 0;
    for(iter = inter.begin(); iter != inter.end(); iter++){
        sum += amp[*iter] * bmp[*iter];
    }
    cout << sum << endl;
}

3. Markdown渲染器

//会者不难,难者不会。好复杂,但是懂了就懂了
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define PSI pair<string, int>
const int N = 1e5 + 5;
int w, lastspace = 0;  //lastspace表示上一个 s 是否为空行
string s;
ll ans;
vector<PSI> store;  //分为三类: 1 表示段落, 2 表示项目列表首项目, 3 表示项目列表非首项目
bool isspace(string str){
    rep(i, 0, (int)str.length() - 1)  //注意length()返回值不是int类型,是size_t类型,需要转换!!!
        if(str[i] != ' ') return 0;
    return 1;
}
string delete_space(string s){  //删除开头结尾的空格
    int l  = 0, r = s.size() - 1;
    while(s[l] == ' ') l++;
    while(s[r] == ' ') r--;
    return s.substr(l, r - l + 1);
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin >> w;
    //预处理
    while(getline(cin, s)){  //处理第一个带内容行.因为没有上一行,不能判断
        if(isspace(s)) continue;
        if(s[0] == '*' && s[1] == ' ') store.push_back({delete_space(s.substr(2)), 2});
        else store.push_back({delete_space(s), 1});
        break;
    }
    lastspace = 0;
    while(getline(cin, s)){
        if(isspace(s)){
            lastspace = 1;
            continue;
        }
        if(lastspace == 1){  //上一行为空行
            if(s[0] == '*' && s[1] == ' ')  //项目列表首项目首行
                store.push_back({delete_space(s.substr(2)), 2});
            else  //段落
                store.push_back({delete_space(s), 1});
        }
        else{  //上一行非空行
            PSI &Last = store.back();  //引用可直接加
            if(Last.second != 1){  //在项目列表中
                if(s[0] == '*' && s[1] == ' ')  //此行为项目列表非首项目的首行
                    store.push_back({delete_space(s.substr(2)), 3});
                else if(s.length() >= 2 && s.substr(0, 2) == "  ")  //此行为项目列表的项目中的非首行
                    Last.first += (" " + delete_space(s.substr(2)));  //此时有可能上一行项目首行为空白,则此行加入不应加空格。此判断在最后统计时考虑,这里不做讨论
                else  //此行为段落
                    store.push_back({delete_space(s), 1});
            }
            else{  //在段落中
                if(s[0] == '*' && s[1] == ' ')  //此行为项目列表首项目的首行
                    store.push_back({delete_space(s.substr(2)), 2});
                else  //此行均视为段落
                    Last.first += " " + delete_space(s);
            }
        }
        lastspace = 0;
    }
    //渲染
    ans = 0;
    rep(i, 0, (int)store.size() - 1){
        PSI &now = store[i];
        string str = now.first;
        if(i > 0 && now.second != 3) ans++;
        int nowwide = w - (now.second == 1 ? 0 : 3);  //根据段落和项目区分终端宽度
        if(str == ""){  //空白行列表也算一行,细节
            ans++;
            continue;
        }
        for(int i = 0; i < str.size(); i += nowwide){
            while(str[i] == ' ' && i < str.length()) i++;
            ans++;
        }
    }
    cout << ans << endl;
}

4. 1246(digits)

  • 1246(digits)

  • 转移方程:

    i − 1 i-1 i14,641,16
    i i i124616264142444661626466
//回溯 + 矩阵快速幂dp
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define PSI pair<string, int>
const int N = 1e2 + 5;
const ll mod = 998244353;
int n, cnt;
ll k, res = 0;
string s;
struct AC{
    ll m[N][N];
}mi, E, power, powertmp;
string formap[N] = {"x", "1", "2", "4", "6", "16", "26", "41", "42", "44", "46", "61", "62", "64", "66"};
map<string, int> mp;
map<string, string> mpp;
PSI pr[N];
void Set(int y, int x){
    power.m[x][y] = 1;
}
AC mul(AC x, AC y){
    AC c;
    rep(i, 1, n) rep(j, 1 ,n) c.m[i][j] = 0;
    rep(i, 1, n) rep(j, 1 ,n){
        rep(k, 1, n){
            c.m[i][j] += x.m[i][k] * y.m[k][j] % mod;
            c.m[i][j] %= mod;
        }
    }
    return c;
}
int pow(AC power, ll k, int id){
    AC c = E;
    while(k > 0){
        if(k % 2 == 1) c = mul(c, power);
        power = mul(power, power);
        k >>= 1;
    }
    // rep(i, 1, 14){
    //     rep(j, 1, 14) cout << c.m[i][j] << " ";
    //     cout << endl;
    // }
    return c.m[2][id] % mod;
}
inline void init(){
    //设置矩阵大小
    n = 14, cnt = 0;
    //离散化
    rep(i, 1, n) mp[formap[i]] = i;
    //转移矩阵,用作矩阵快速幂
    /* 14 x 14:
    0 1 0 0 0 0 0 0 0 0 0 0 0 0 
    0 0 1 0 0 0 0 0 0 0 0 0 0 0
    1 0 0 1 1 0 0 0 0 0 0 0 0 0
    0 0 1 1 0 0 0 0 0 0 0 0 1 0
    0 0 0 0 0 1 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 1 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 1 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 1 0
    0 0 0 0 0 0 0 0 0 0 1 0 0 0 
    0 0 0 0 0 0 0 0 0 0 0 0 0 1 
    0 0 0 0 0 0 0 1 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 1 0 0 0 0 0
    0 0 0 0 0 0 1 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 1 0 0 0 0
    */
    Set(mp["1"], mp["4"]);
    Set(mp["2"], mp["1"]);
    Set(mp["4"], mp["2"]), Set(mp["4"], mp["6"]);
    Set(mp["6"], mp["4"]), Set(mp["6"], mp["6"]);
    Set(mp["16"], mp["4"]);
    Set(mp["26"], mp["16"]);
    Set(mp["41"], mp["64"]);
    Set(mp["42"], mp["61"]);
    Set(mp["44"], mp["62"]);
    Set(mp["46"], mp["26"]), Set(mp["46"], mp["66"]);
    Set(mp["61"], mp["44"]);
    Set(mp["62"], mp["41"]);
    Set(mp["64"], mp["6"]), Set(mp["64"], mp["42"]);
    Set(mp["66"], mp["46"]);
    //构造单位矩阵E
    rep(i, 1, n) rep(j, 1, n) E.m[i][j] = (i == j ? 1 : 0);
}
string PER(string s){
    int v = 0;
    string tmp = "";
    while(v < s.length()){
        // cout << s[v] << " " << s[v + 1] << endl;
        if(s[v] == '1'){
            if(s[v + 1] == '6' || v + 1 >= s.length()) tmp += "4", v += 2;
            else return "0";
        }
        else if(s[v] == '2') tmp += "1", v += 1;
        else if(s[v] == '4') tmp += "2", v += 1;
        else if(s[v] == '6'){
            if(s[v + 1] == '4' || v + 1 >= s.length()) tmp += "6", v += 2;
            else return "0";
        }
    }
    return tmp;
}
void dfs(string s, int len){
    if(s.length() <= 2){
        rep(i, 1, 14)
            if(s == formap[i]){
                pr[++cnt] = {s, k - len};
                return;
            }
        return;
    }
    //开头第一个数字决定分支
    if(s[0] == '1'){//"4" --> "1(6)"
        if(s[1] == '6') dfs("4" + PER(s.substr(2, s.length() - 2)), len + 1);
    }
    else if(s[0] == '2'){//"1" --> "2"
        dfs("1" + PER(s.substr(1, s.length() - 1)), len + 1);
    }
    else if(s[0] == '4'){//"2" --> "4" & "6" --> "(6)4"
        dfs("2" + PER(s.substr(1, s.length() - 1)), len + 1);
        dfs("6" + PER(s.substr(1, s.length() - 1)), len + 1);
    }
    else if(s[0] == '6'){//"6" --> "6(4)" & "4" --> "(1)6"
        if(s[1] == '4') dfs("6" + PER(s.substr(2, s.length() - 2)), len + 1);
        dfs("4" + PER(s.substr(1, s.length() - 1)), len + 1);
    }
    return;
}
int main(){
    cin >> k >> s;
    init();
    //处理|s|>2 的情况
    dfs(s, 0);
    rep(i, 1, cnt){
        powertmp = power;  //pow 操作修改了powertmp所以
        res += pow(powertmp, pr[i].second - 1, mp[pr[i].first]);
        res %= mod;
    }
    cout << res;
}

5. 乔乔和牛牛逛超市

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值