蓝桥杯 数学与动态规划篇

  1.   蓝桥杯实用小技巧
  2. C++蓝桥杯基础知识常用整理

陆续更新----还在专题复习中 没到算法笔记 到时会有更多的干货哦,比如可能会出现的树图(Floyd,SPFA,平衡二叉树的左旋右旋等等)

2022年居然没考 哈哈哈哈哈哈

目录

          数学

动态规划  

推荐几个刷题网站


数学

 这个方法是在PAT的《算法笔记》里面学到的 开始的时候vis数组全部为false(默认bool数组都是fasle) 只要是质数的倍数 那就一定不是质数 则可以全部转为true 

同时ans 还可以记录2到n的质数个数

for(int i=2;i<n;i++){//寻找质数
            if(!vis[i]){
                ans++;
                for(int j=i+i;j<n;j+=i){
                    vis[j]=true;
                }
            }
        }
//求得一个数的所有约数
    for(int i=1;i<=sqrt(n);i++){
        if(n%i==0){
        nums.push_back(i);
       	 if(i*i!=n)nums.push_back(n/i);
		}
    }

 

int gcd(int a,int b)//求a,b最大公约数 
{
    if(b==0)return a;
    return gcd(b,a%b);
}
int f(int y)//判断闰年 
{
    if(y%4==0&&y%100!=0||y%400==0) return 1;
    return 0;
}
  求俩矩形覆盖面积
 int overlapWidth = min(ax2, bx2) - max(ax1, bx1);
 int overlapHeight = min(ay2, by2) - max(ay1, by1);
  int overlapArea = max(overlapWidth, 0) * max(overlapHeight, 0);

 原题链接223. 矩形面积 - 力扣(LeetCode) (leetcode-cn.com)

验证2的幂:(n & (n-1)) == 0

验证4的幂:(n & (n-1)) == 0&& (n % 3 == 1)

//哈希 解决循环数

 unordered_map<int,int> map;
        int index=0;
        while(n!=1&&!map.count(n)){
            map[n]=index++;
            n=f(n);
        }

//快速幂

const int MOD = 1337
 int pow(int x, int n) {
        int res = 1;
        while (n) {
            if (n % 2) {
                res = (long) res * x % MOD;
            }
            x = (long) x * x % MOD;
            n /= 2;
        }
        return res;
    }

//分数到小数

也是类似于字符串

      
      int num=numerator;//分子
      int den=denominator;//分母
      string ans="";
      if(num*den<0)ans+="-";//如果分子分母相乘为负 前面加一个‘-’号
      num=abs(num);//分子取绝对值
      den=abs(den);//分母取绝对值
      ans+=to_string(num/den);//将俩位相除的值放到字符串里面去
      int n =num%den;//如果俩数取余为0 则没有小数
      if(n==0){
          return ans;
      }

如果有小数 或者有无限循环小数 就要具体分析了

详细小伙伴们可以做下leetcode的这题练练手

 https://leetcode-cn.com/problems/fraction-to-recurring-decimal/


//常见动态转移方程

最大连续子序列和:
dp[i]=m a x ( A[i] , dp[i-1]+A[i])

最长不下降子序列
dp[i] = m a x (dp[i] , dp[j]+1)

三角形最小路径和:
dp[i][j]=min(dp[i+1][j],dp[i+1][j+1])+f[i][j];

//较为复杂的动态转移方程

//最长公共子序列(LCS)
dp[i][j]表示字符串A的i号位和字符串B的j号位之前的LCS长度

边界:dp[i][0] = dp[0][j]=0(0<=i<=n,0<=j<=m)

这样状态dp[i][j]只与其之前的状态有关,由边界出发就可以得到整个dp数组,最后dp[n][m]就是答案

//状态转移方程:

for(int i=1;i<=lenA;i++)

    for(int j=1;j<=lenB;j++)

        if(A[i]==B[j]){

               dp[i][j]=dp[i-1][j-1] + 1;

         }else{

             dp[i][j]=max(dp[i-1][j],dp[i][j-1]);   

        }

最长回文子串练习https://leetcode-cn.com/problems/longest-palindromic-substring/ 

//最长回文子串
dp[i][j] 表示S[i]到S[j] 是否是回文子串
边界:dp[i][i]=1,dp[i][i+1] = (S[i] == s[i+1])?1:0

//初始化
for(int i=0; i<length; i++) {

	dp[i][i]=1;

	if(i<length-1) {

		if(s[i]==s[i+1]) {

			dp[i][i+1]=1;

		}
	}
}

//状态转移方程
for(int l=2; l<=length; l++) {

	for(int i=0; i+l-1<length; i++) {

		int j = i+l-1;

		if(i+1>=j&&s[i]==s[j]) {

			dp[i][j]=1;

		}
		if(s[i]==s[j]&&dp[i+1][j-1]==1) {

			dp[i][j]=1;

		}
		if (dp[i][j] && j - i + 1  > maxLen) {

			maxLen = j - i + 1 ;

			begin = i;
		}
	}
}

01背包动态转移方程:https://www.acwing.com/problem/content/2/

//物品只能选一件
//i表示前i个物品 j表示容量 j<=m
二维:f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i](从小到大枚举)
一维:f[v]=max(f[v],f[j-v]+w[i])(从大到小枚举)

//n是物品个数,m是最大容量
for(int i=1;i<=n;i++){

        int v,w;

        cin>>v>>w;

        for(int j=m;j>=v;j--){

            dp[j]=max(dp[j],dp[j-v]+w);

        }
    }

 

完全背包动态转移方程:https://www.acwing.com/problem/content/3/

//状态转移方程---物品可以选无限件
f[j]=max{f[j],f[j-v[i]]+w[i]}
//实例 v表示物品体积 w表示物品价值
for(int i=0;i<n;i++){

        int v,w;

        cin>>v>>w;

        for(int j=v;j<=m;j++)//(从小到大)

        dp[j]=max(dp[j],dp[j-v]+w);
    }

多重背包问题一:
跟一维的01背包类似https://www.acwing.com/problem/content/4/

//含义是物品最多可以选k件 
for(int i=0;i<n;i++){

        int v,w,s;

        cin>>v>>w>>s;

        for(int j=m;j>=v;j--)

            for(int k=1;k<=s&&k*v<=j;k++)

                dp[j]=max(dp[j],dp[j-k*v]+k*w);
    }

多重背包问题二(当数据量比较大的时候):https://www.acwing.com/problem/content/5/
二进制优化 将多重背包转化为01背包问题

for(int k = 1;k <= s;k *=2){
           
     s -=k;
           
     goods.push_back({v * k,w * k});
       
 }
       
 if(s > 0)   goods.push_back({v * s,w * s});

for(auto good : goods) {

	for(int j = m; j >= good.v; j --) {

		dp[j] = max(dp[j],dp[j - good.v] + good.w);

	}
}

二维背包问题https://www.acwing.com/problem/content/8/

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

const int maxn = 1010;
int n,v,m;

int dp[maxn][maxn];

int main(){
    cin>>n>>v>>m;

    for(int i=0;i<n;i++){

        int a,b,c;

        cin>>a>>b>>c;

        for(int j=v;j>=a;j--){

            for(int k=m;k>=b;k--)

            dp[j][k]=max(dp[j][k],dp[j-a][k-b]+c);

        }
    }

    cout<<dp[v][m];

    return 0;
}

背包问题求方案数https://www.acwing.com/problem/content/11/

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010, mod = 1000000007;

int n, m;
int f[N], g[N];
int v[N], w[N];

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i];

    for (int i = 0; i <= m; i ++ ) g[i] = 1;

    for (int i = 1; i <= n; i ++ )

        for (int j = m; j >= v[i]; j -- )
        {
            int left = f[j], right = f[j - v[i]] + w[i];

            f[j] = max(left, right);

            if (left > right) g[j] = g[j];

            else if (left < right) g[j] = g[j - v[i]];

            else g[j] = g[j] + g[j - v[i]];

            g[j] %= mod;
        }

    cout << g[m] << endl;

    return 0;

}

 

以上背包问题的解决方法都出自y大佬的视频和acwing题库

还有混合背包问题 二维费用背包问题 背包问题具体方案等等 要的小伙伴自取 

推荐几个刷题网站

leetcode 上面也很多出的好的题 可以分专题刷 网站都分类好了的

蓝桥云课 这里面有蓝桥杯的真题 我觉得比那个蓝桥杯官方的oj好用的多

蓝桥杯VIP题 这里面没有蓝桥杯的VIP题 这里面没有蓝桥杯的VIP题 这里面没有蓝桥杯的VIP题 重要的事情说三遍

AcWing NOI金牌北京大学y大佬一个人做的 常常有比赛 出的题都挺有意思的 里面涵盖了所有背包问题 推荐

 

 

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

owensweat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值