ccf csp认证历年题

本文介绍了CCF CSP认证的历年真题,强调了读题和选择合适算法的重要性。文章通过分析不同题目的解题思路,如仓库规划、因子化简、坐标变换等,探讨了如何优化时间复杂度,如利用前缀和、前缀积以及unordered_map等数据结构。同时,文章提醒考生注意编程细节,如类型转换、未初始化警告和动态规划的应用。
摘要由CSDN通过智能技术生成

根据时间复杂度选择算法

读题

最好先带着样例中的输入输出分别对应什么这个问题,去题目中找。可把样例复制下来,注释一下含义(复制题目)。再确定下标、取值范围。有草稿纸可打草稿。

CCF-CSP考试历年真题题型分类 - AcWing

编程知识

while(n--)与while(--n):前者是先判断后--,后者相反,故后者循环次数为n .

202312-1 仓库规划

#include <bits/stdc++.h>
using namespace std;

//寻找编号最小上级
int main() {
       /* 
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);*/
    int N = 0, M = 0; // 定义两个整数变量N和M,分别用于存储仓库的行数和列数
    cin >> N >> M; // 从标准输入读取N和M的值
    vector<vector<int> > warehouse(N + 1, vector<int>(M)); // 创建一个二维向量warehouse,大小为N+1行M列(即N+1个vector<int>(M)),所有元素初始化为0.  第0行在这里没用。
    for (int i = 1; i <= N; i++) { // 循环读取warehouse的元素
        for (int j = 0; j < M; j++) {
            cin >> warehouse[i][j]; // 从标准输入读取warehouse[i][j]的值
        }
    }
    for (int i = 1; i <= N; i++) { // 分别分析仓库1~N
        int res = 0; // 默认为没有上级
        for (int j = 1; j <= N; j++) { // 循环遍历所有行(与每一个仓库对比)
            if (i != j) { // 如果当前行i不等于比较行j(自己不与自己比)
                bool flag = true; // 用于标记是否找到上级,默认为j仓库是,对比之后不是会改为false,没改则是上级。
                for (int k = 0; k < M; k++) { // 循环遍历所有列
                    if (warehouse[i][k] >= warehouse[j][k]) { // 如果当前行的第k列不小于比较行的第k列(则该仓库不是上级)
                        flag = false; //该仓库不是上级,不用再比下去了
                        break; // 跳出循环
                    }
                }
                if (flag) { //
                    res = j; // 将比较行j的值赋给res(记录上级编号)(由于是按编号从小到大的顺序来找的,故先找到的就是编号最小上级,不用再继续找)
                    break; // 跳出循环
                }
            }
        }
        cout << res << endl; // 输出res的值,并添加一个换行符
    }
    return 0; // 程序结束
}

202312-2 因子化简(模板题)

法一:利用朴素筛法先求素数表,再分解质因数

#include <iostream>
#include <cmath>
#include <vector>
using namespace std;

   const int M = sqrt(1e10)+1; 
   int NotPrime[M];//默认为都是素数(0代表是),下标与数对应。
   vector<int> prime; //素数表

void get_prime() //构造素数表,只需2~sqrt(1e10)中的素数
{
    for(int i=2;i<M;i++) //只需2~sqrt(1e10)中的素数
    {
        if(!NotPrime[i]) //若是素数(注意这里和“默认0为是”的搭配)
        {prime.push_back(i);
        for(int j=i*i;j<M;j+=i) //筛出素数
                NotPrime[i]=1;//标记合数
        }
    }
}

int main()
{
	ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
   long long  n;
   int k,q;//阈值,行数
   cin>>q;
   get_prime();
   while(q--)
{
    long long ans=1;
    cin>>n>>k;
    for(int i=0;i<prime.size()&&n>prime[i];i++)
        {   int cnt=0;
            while(n%prime[i]==0)//是质因数
            {
             n/=prime[i];
             cnt++;//计算幂次
            }
            if(cnt>=k) ans*=pow(prime[i],cnt);//在模板基础上对题目要求进行处理
        }
      cout<<ans<<endl;
}
}

法二:试除法分解质因数

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
   long long  n;
   int k,q;//阈值,行数
   cin>>q;
   while(q--)
{
    long long ans=1;
    cin>>n>>k;
    for(int i=2;i<=n/i;i++)
	{
		if(n%i==0) //i一定是质数,因为此时2到i-1的质因子已经被除干净了.即若是因子,则一定是质因子。
		{
			int cnt=0;
			while(n%i==0)
			{
				n/=i;
				cnt++;
			}
			if(cnt>=k) ans*=pow(i,cnt);//只累乘幂次>=k。
		}
	}
      cout<<ans<<endl;
}
}

202309-1 坐标变换(其一)

非常easy。感悟是:没必要用typedef pair<int,int> PII,用PII来定义坐标,做加法代码更长的。坐标不就是两个int嘛,写好注释一下记得就行。以下代码没必要看了。

#include<bits/stdc++.h>
using namespace std;

int main()
{ 
    int x=0,y=0;
    int n,m,dx,dy;
    cin>>n>>m;
    while(n--)
    {
        cin>>dx>>dy;
        x+=dx;
        y+=dy;
    }
    while(m--)
    {
        cin>>dx>>dy;
        cout<<x+dx<<' '<<y+dy<<endl;
    }
}

202309-2 坐标变换(其二)(2.22)

我的第一思路(暴力思路):

每次查询都根据所给范围遍历做操作,最坏时间复杂度为O(mn),题目m,n最大为1e5,最坏的次数到1e10,题目限制2s,即大概1e8次操作,所以提交会出现部分数据超时。只能拿80分。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值