根据时间复杂度选择算法
读题
最好先带着样例中的输入输出分别对应什么这个问题,去题目中找。可把样例复制下来,注释一下含义(复制题目)。再确定下标、取值范围。有草稿纸可打草稿。
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分。
<