CCFCSP2305

发布时间 2023-12-04 18:55:53作者: Wennz-y

写在前面

CSP(计算机软件能力认证考试),主要覆盖大学计算机专业所学习的程序设计,数据结构,算法以及相关的数学基础知识。

包括但不限于:

  • 程序设计基础:
        逻辑与数学运算,分支循环,过程调用(递归),字符串操作,文件操作,etc.

  • 数据结构:
        线性表(数组,队列,栈,链表),树(堆,排序二叉树),哈希表,集合与映射,图,etc.

  • 算法与算法设计策略:
        排序与查找,枚举,贪心策略,分治策略,递推与递归,动态规划,搜索,图论算法,计算几何,字符串匹配,线段树,随机算法,近似算法, etc.

考试模式:

  • OI机制(分点给分

  • 4h内完成5道题

题型大致分布&注意事项:(据一位CSP420分的学姐说

  • 第一题:水题
        稍有编程经验,20+-行代码可搓完
    1.注意细节:
        long long
        边界
        特殊情况
    2.用文件读入可节省大量时间
    3.宏定义节省for循环书写用时
    #define _for(i , a , b) for(int i=a; i<b; i++) 4.声明数组大小时,用const定义的伪常量方便修改

     const int N=1007
     int Num[N] , Sum[N];
     char str[N]
    
  • 第二题:小模拟
        处理比较简单的问题,需要梳理简单的逻辑和过程
    1.多重循环,接近n^2的复杂度。一般是时序题,熟练运用排序、多元数组、STL会有奇效
    2.必备STL神器
    string:字符串查找、拼接、花式读入
    set:自动排序,去重
    vector:盲开数组的首要选择
    priority_queue:自定义优先级的队列
    map:不同类型数据的双向字典

  • 第三题:大模拟,字符串处理
        处理复杂的问题,涉及字符串的问题居多
    1.熟练掌握各种输入函数与字符串的处理,DFS, BFS,
    2.会设计复杂的层次化结构
    3.题库
    ZJU:acm.zju.edu.cn
    PKU:acm.pku.edu.cn/JudgeOnline
    HDU:acm.hdu.edu.cn
    USACO:train.usaco.org/usacogate
    Codeforces:codeforces.com
    4.题目不难,只是变态(?)

  • 第四题:算法题
        难度中,重点考图论和动规
    1.熟练掌握最小生成树、最短路径、简单递推
    2.会强连通分量,欧拉函数,动规优化(四边形优化,etc.
    3.会将DFS转变为非递归式避免爆栈(80‘->100’)

  • 第五题:算法题
        难度高,设计算法面很多,数据量很大,需要堆算法极致优化,很难满分
    1.熟练掌握各种程序设计算法,以及对时间、空间的优化
    2.快速coding, debug
    3.精神状态极佳

骗分建议:

  • 贪心

  • 搜索+剪枝

  • 暴力打表:简单数学分析+猜测找规律

  • 分类讨论

  • 固定输出


-1.重复局面

分析

用上STL送昏

  • 题目有点绕

  • 读不懂==刚开始做CSP的正常现象

根据样例,每8行构成一个棋局,采用字符串数组string的数据结构:

  • 读入n(代表该盘棋有n步

  • 读入每一步的8行局面,每8行合并成一个string串(含64个字符)

  • 设置计数器count,default为1

  • for循环与前面每一个string串,比较,相等则count++

  • 输出count

AC:

#include<iostream>
#include <string>

using namespace std;
int main(){
    int n;
    cin>>n;
    string chess[110];

    for(int i=1;i<=n;i++){ //每盘
        for(int j=1;j<=8;j++){ //每行
            string temp;
            cin>>temp;
            chess[i]=chess[i]+temp;
        }
        int count=1;
        for(int k=1;k<i;k++){
            if(chess[k]==chess[i])
                count++;
        }
        cout<<count<<endl;
    }
    return 0;
)

-2矩阵运算

分析

顺序模拟会显示超时(有时候一个人敲代码就挺无助的。。。

  • tmp =  Q x KT(此时tmp是nxn大小,会爆

  • tmp = W · tmp

  • ans = tmp x V

  • 达咩

所以可以先算后面两个矩阵,这样时间复杂度就可以过了

  • tmp = KT x V(此时是dxd大小,安全

  • ans = Q x tmp

  • (第一遍做的时候还没复习线代,死活没想到这一点

  • 两矩阵运算时,会用到三重for循环

  • ijk,一般纸上模拟一遍就有思路了

测试数据:

3 2
1 2
3 4
5 6
10 10
-20 -20
30 30
6 5
4 3
2 1
4 0 -5

UNAC:k是矩阵叉乘的内标

  • 超时超内存

  • 限制5s, 512MB

  • 这串码5.062s, 771.3MB

#include<bits/stdc++.h>
using namespace std;
int n,d;
const int N=10010,D=30;
int Q[N][D],K[N][D],V[N][D],W[N];
long long tmp[D][D],ans[N][N];

int main(){
    cin>>n>>d;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=d;j++)
            cin>>Q[i][j];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=d;j++)
            cin>>K[i][j];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=d;j++)
            cin>>V[i][j];
    for(int i=1;i<=n;i++)    cin>>W[i];

    //tmp=KTxV
    for(int i=1;i<=n;i++)
        for(int j=1;j<=d;j++)
            for(int k=1;k<=n;k++)
                tmp[i][j]+=K[k][i]*V[k][j];
                //tmp[i][j]+=K[k][j]*V[k][j];戳辣
                //在列的位置,但是有i个
    //ans=Qxtmp
    //ans*=W
    for(int i=1;i<=n;i++)
        for(int j=1;j<=d;j++){
            for(int k=1;k<=n;k++)  //这里错了k=d
                ans[i][j]+=Q[i][k]*tmp[k][j];
            ans[i][j]*=W[i];
        }

    for(int i=1;i<=n;i++){
        for(int j=1;j<=d;j++)
            cout<<ans[i][j]<<' ';
        cout<<endl;
    }    

    return 0;
}

AC:

#include<bits/stdc++.h>
using namespace std;
const int N=10010,D=30;
long long tmp[D][D],ans[N][N];
int n,d;
int Q[N][D],K[N][D],V[N][D],W[N];

int main(){
    cin>>n>>d;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=d;j++)
            cin>>Q[i][j];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=d;j++)
            cin>>K[i][j];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=d;j++)
            cin>>V[i][j];
    for(int i=1;i<=n;i++)    cin>>W[i];

    //tmp=KTxV
    for(int i=1;i<=n;i++)
        for(int j=1;j<=d;j++)
            for(int k=1;k<=n;k++)
                tmp[i][j]+=K[k][i]*V[k][j];

    //ans=Qxtmp
    //ans*=W
    for(int i=1;i<=n;i++){
        for(int j=1;j<=d;j++){
           for(int k=1;k<=d;k++) //for(int k=1;k<=n;k++)
                ans[i][j]+=Q[i][k]*tmp[k][j];
            ans[i][j]*=W[i];
            cout<<ans[i][j]<<' ';
        }
        cout<<endl;
    }

    return 0;
}