基础框架(一定要记得非常熟练)

#include<bits/stdc++.h>
using namespace std;
int main()
{
	return 0;
}

cout<<fixed<<setprecision(2)<<x;//保留两位小数输出

&&(与,同时满足),||(或,只要有一个满足),!(取反)

if(a) 等价于如果a!=0
if(!a) 等于于如果a==0


一级

闰年判断

bool st=false;
if (y%4==0&&y%100!=0||y%400==0)
{
  st=true;
}
if(st) //闰年的执行语句
{}
else //非闰年执行语句
{}


基础时间问题

1年12月,1天24小时,1个小时60分钟,1分钟60秒
1,3,5,7,8,10,12为大月31天
4,6,9,11为小月 30天

h(小时),m(分钟),s(秒)

int t=h*3600+m*60+s 可以得到当前时间距离0点的秒数

h=t/3600 可以得到距离0点的秒数对应的小时数
m=(t%3600)/60 可以得到距离0点的秒数对应的分钟数
s=t%60 可以得到对应的秒数


  
int ge=x%10;
int shi=x/10%10;
int bai=x/100%10;
int qian=x/1000%10;

int x=a/b;表示a个苹果分给b个人一共可以分成多少分
int y=a%b;表示a个苹果分给b个人还剩下多少(也可以表示完整周期多出来的数目,等于0表示恰好分完)

int t=(a+b-1)/b;表示a除以b的上取整的结果,类似于如果4个小时吃一个苹果,那么10个小时吃过三个苹果3=(10+4-1)/3

同理也可以得到一年距离0天的数目d
int w=(t+6)/7就可以得到第几周了
int d1=t%7,就可以得到是第w周的星期d1,如果d1==0说明是周天。
  
if(a%b==0) 表示a是b的倍数
if(a%b!=0) 表示a不是b的倍数

for/while循环之中continue是继续下次循环,break是跳出当前层循环。

//因数,约数
int s1=0,s2=0;
for(int i=1;i<=n;i++) //枚举1到n的范围
{
    if(n%i==0) //说明i是n的因数
    {
        s1+=1;//统计1到n中n的个数
        s2+=i;//统计1到n中n的因数之和
    }
}

累乘
int s=1;
for(int i=1;i<=n;i++)
{
    int x;
    cin>>x;
    s=s*x;  
}

pow(a,b)得到a的b次方


累加
int s=1;
for(int i=1;i<=n;i++)
{
    int x;
    cin>>x;
    s=s+x;  
}
最大
int mav=0;
for(int i=1;i<=n;i++)
{
    int x;
    cin>>x;  
    if(i==1||x>maxv)
    {
        maxv=x;
    }
}
判断是否符合规则的结构,如x*x*x=n
bool st=false; 最开始没有
for(int x=1;x*x*x<=n;x++) //枚举x的所有范围
{
    if(x*x*x==n)
    {
         st=true;//找到了就更新状态
    }
}
if(st) 可以找到

二级

图形输出(i表示行,j表示列)
for(int i=1;i<=n;i++) //枚举行
{
    for(int j=1;j<=m;j++) //枚举列(正方形的时候m=n)
    {
       //根据不同的情况写if筛选图形(一般是if,else if(),else 结构)    
    }
    cout<<endl;//第i行输出以后进行换行
}
第一列和最后一列 j==1||j==m
第一行或者是最后一行 i==1||i==n
左上到右下的对角线 i==j
左下到右上的对角线 i+j==n+1
中间的行(n+1)/2==i,中间的列(m+1)/2==j

拆数
int t=n;
int s1=0(位数),s2=0(每位数的和),s3=0(翻转数);
while(t)
{
  int ge=t%10;
  s1++;         //统计位数
  s2+=ge;       //每个数的和
  s3=s3*10+ge;  //翻转数
  t/=10;
}
//拆数完成后,t的值为0

bool st=true;
if(st<2)
{
    st=false;
}
for(int i=2;i<=n/i;i++)
{
    if(n%i==0)
    {
        st=false;
    }
}
if(st) //满足质数条件

对于数据范围较小的数据
int cnt=0;
for(int i=1;i<=n;i++)
{
    if(n%i==0)
    {
        cnt++;
    }
}
if(cnt==2) //说明是质数(素数)

斐波那契数列
初始化 a[1]=1,a[2]=2; //第一项是1,第二项是2
for(int i=3;i<=n;i++) //从第三项开始是前两项之和
{
    a[i]=a[i-1]+a[i-2];
}


多组数组的状态判定(判断x*x+y*y==a)
int t;
cin>>t;
while(t--)
{
   cin>>a;
   int cnt=0;//清空状态(最开始找不到)
   for(int x=1;x*x<=n;x++) //枚举x的情况
   {
       for(int y=x+1;y*y<=n;y++) //枚举y的情况(如果x和y是相同不同数,可以让y=x+1,如果y可以等于x,则让y=1)
       {
           if(x*x+y*y==a) //根据题目要求改变状态
           {
              cnt++;
          }
       }
   }
}

和行列有关的矩阵输出([GESP202503 二级] 等差矩阵)
for(int i=1;i<=n;i++)
{
    for(int j=1;j<=m;j++)
    {
        int t=i*j;//根据题目要求计算
        cout<<t<<endl;
    }
    cout<<endl;
}

## 三角形结构输出()
for(int i=1;i<=n;i++)
{
    for(int j=1;j<=i;j++)
    {
        //根据题目要求执行
    }
    cout<<endl;//输出换行符号
}

状态判断类题目([GESP202309 二级]数字黑洞)
int cnt=0;
while(n!=495)
{
     cnt++;
     根据题目要求进行操作
}

多重枚举状态判定(类似于白钱百鸡)
int cnt=0;//初始状态
for(int a=0;a<=n;a++) //a的范围
{
    for(int b=0;b<=m;b++) //b的范围
    {
        for(int c=0;c<=m;c++) //c的范围
        {
            if() //根据题目要求去筛选
        }
    }
}
//根据状态结果去输出

四级

拿到题目一定要先想能不能排序,需不需要排序,排序了以后应该如何写。

sort(s+a,s+b+1); 对s[a]到s[b]进行从小到大排序

struct Stu{
  int sc;
  string name;
};
Stu s[100];
bool cmp(Stu a,Stu b)
{
    if(a.sc>b.sc) return 1;//成绩从高到低
    if(a.sc==b.sc&&a.name<b.name);//成绩相同,名字小的在前面
    return 0; //不符合规则
}
sort(s+1,s+n+1,cmp);//将s[1]到s[n]按照cmp的规则进行排序

田忌赛马模型
两个有序数组
int cnt=0;
for(int i=1,j=1;i<=n;i++)
{
    if() 满足j移动的状态
    {
        //状态改变
        j++; 移动
    }
}

一维区间序列的枚举
for(int l=1;l<=n;l++)
{
    for(int j=l;j<=r;j++)
    {
        //初始化当前区间状态
        for(int k=l;k<=r;k++) //枚举区间的每个位置
        {
             //更新状态
        }
        //根据l到r这段的结果去更新整个答案
    }    
}

一般表示长度为3的区间每个区间可以用
for(int i=1;i+2<=n;i++)  //保证右端点不会越界
{
    l=i,r=i+2;//整个区间
}


二维区间的枚举
for(int x1=1;x1<=n;x1++)
{
    for(int y1=1;y1<=m;y1++) //矩阵的左上角
    {
        for(int x2=x1;x2<=n;x2++)
        {
            for(int y2=y1;y2<=m;y2++) //矩阵右下角
            {
                //初始化矩阵中的元素状态
                for(int i=x1;i<=x2;i++)
                {
                    for(int j=y1;j<=y2;j++) //枚举区间的每个位置
                    {
                        //根据矩阵中的元素去更新状态
                    }
                }
                //使用矩阵中的元素属性去更新答案
            }
        }
    }
}

二维区间长(l)宽(w)固定
for(int i=1;i+l-1<=n;i++)
{
    for(int j=1;j+w-1<=m;j++)
    {
        x1=i,x2=i+l-1,y1=j,y2=j+w-1;//开始枚举矩阵
    }
}


枚举相邻
for(int j=1;j+1<=n;j++)
{
  //a[j]和a[j+1]都是相邻的
}

int dx[]={-1,1,0,0},dy[]={0,0,-1,1};//上下左右

int dx[]={-1,-1,-1,0,0,1,1,1}; //周围八个位置
int dy[]={-1,0,1,-1,1,-1,0,1};

基于增量的题目([GESP202503 四级] 荒地开垦)

有些题目限定了操作次数,我们可以去枚举所有的位置上的对应的操作,然后根据题目要求去进行判断,这个时候我们可能需要去维护一些额外的数组去统计不同的位置进行操作以后对于周边结构的影响。

五级

自定义排序一定要熟悉


记得有些数据太大了,一定要开 long long 
线性筛质数,分解质因数,倍数求约数,埃式筛质数
合并果子(维护最小的k个元素)

遇到分类的题目移动要想到动态数组vector<数据类型> v

遍历访问
for(auto x:v)
{
    cout<<x<<" "
}

遇到排序去重的题目想到集合set<数据类型> s;

遇到统计类题目或者关系结构想到哈希表 map<类型a,类型b> h

for(auto it:h)
{
      cout<<it.first<<" "<<it.second<<endl;
      //first 是第一个属性对应的内容,second是第二个属性对应的内容
}
.size()可以得到string,set,vector,map的大小

0 comments

No comments so far...