Acwing算法笔记

2024-04-23 1357阅读

温馨提示:这篇文章已超过374天没有更新,请注意相关的内容是否还可用!

Acwing算法笔记

持续更新中…

Acwing算法笔记
(图片来源网络,侵删)

文章目录

  • Acwing算法笔记
    • 第一章
      • 1.快排
      • 2.归并排序
      • 3.整数二分
      • 4.差分
        • c++库模版
        • 二分的记忆方法
        • 5.高精度
        • 第四章:数论
          • 1.判断素数
          • 2.质因数分解
          • 3.快速幂和快速幂求逆元
          • 4.欧几里得定理和拓展欧几里得定理
          • 第五章 STL
            • 1.map
              • 使用map模拟链表
              • 2.unordered_map:
              • 3.priority_queue:
              • 第六章 dp
                • 1.十一讲背包
                  • (1)01背包
                  • (2)完全背包
                  • (3)多重背包1
                  • (4)多重背包2
                  • (5)多重背包3
                  • (6)混合三种背包问题
                  • (7)分组背包问题
                  • (8)二维费用的背包问题
                  • (9)背包问题求方案数
                  • (10)背包问题求具体方案数
                  • (11)01背包装满背包的情况

                    第一章

                    1.快排

                    #include 
                    using  namespace std;
                    const int N = 1e5+10;
                    int main() {
                        int a[N];
                        int n;
                        cin>>n;
                        for (int i = 0; i >a[i];
                        }
                        sort(a,a+n);
                        for (int i = 0; i >k;
                            check(k,n);
                        }
                        return 0;
                    }
                    

                    4.差分

                    定义: 首先给定一个原数组a:a[1], a[2], a[3], a[n];然后我们构造一个数组b : b[1] ,b[2] , b[3], b[i];使得 a[i] = b[1] + b[2 ]+ b[3] +, + b[i];也就是说,a数组是b数组的前缀和数组,反过来我们把b数组叫做a数组的差分数组。换句话说,每一个a[i]都是b数组中从头开始的一段区间和。

                    一维差分结论:给a数组中的[ l, r]区间中的每一个数都加上c,只需对差分数组b做 b[l] + = c, b[r+1] - = c。时间复杂度为O(1), 大大提高了效率。

                    https://www.acwing.com/problem/content/description/799/

                    #include
                    #define int long long
                    typedef long long ll;
                    using namespace std;
                    const int N = 2e5 + 10;
                    const int mod  = 998244353;
                    void solve(){
                        int n,m;
                        cin>>n>>m;
                        vector a(n+1,0);
                        for (int i = 1; i 
                            cin>a[i];
                        }
                        vector b(n+10,0);
                        for (int i = 1; i 
                            b[i] = a[i] - a[i-1];
                        }
                        while(m--){
                            int l,r,c;
                            cin>l>>r>>c;
                            b[l]+=c;
                            b[r+1] -= c;
                        }
                        int sum = 0;
                        for (int i = 1; i 
                            a[i] = a[i-1] + b[i];
                            cout
                        ios::sync_with_stdio(false);
                        cin.tie(0);
                        int t = 1;
                        //cint;
                        while(t--){
                            solve();
                        }
                        return 0 ;
                    }
                    
                      while (l > 1;//(加)
                        if(q[mid] = 0, B >= 0
                    {
                        vectorC;
                        int t = 0;
                        for (int i = 0; i >a>>b;
                        vector A,B;
                        for(int i = a.size() - 1;i >= 0;i --){
                            A.push_back(a[i]-'0');
                        }
                        for(int i = b.size() - 1;i >= 0;i --){
                            B.push_back(b[i]-'0');
                        }
                        auto C = add(A,B);
                        for(int i = C.size() - 1; i >= 0;i --){
                            cout 
                        ios::sync_with_stdio(false);
                        cin.tie(NULL),cout.tie(NULL);
                        int t = 1;
                        //cin>t;
                        while(t--){
                            solve();
                        }
                        return 0 ;
                    }
                    

                    高精度减法(https://www.acwing.com/problem/content/794/)

                    #include
                    #define int long long
                    typedef long long ll;
                    using namespace std;
                    const int N = 1e5 + 10;
                    const int mod  = 1e9 + 7;
                    //首先判断A和B的大小
                    bool cmp(vector &A,vector &B){
                        if(A.size() != B.size()) return A.size() > B.size();
                        for (int i = A.size()-1; i >= 0; i -- ){
                            if(A[i] != B[i]){
                                return A[i] > B[i];
                            }
                        }
                        return true;    //  A和B相等
                    }
                    vector sub(vector &A,vector &B)  // C = A - B, A >= 0, B >= 0
                    {
                        vector C;
                        int t = 0;
                        for (int i = 0; i  1 && C.back() == 0) C.pop_back();  //删除前导零
                        return C;
                    }
                    void solve(){
                        string a,b;
                        cin>>a>>b;
                        vector A,B;
                        for(int i = a.size() - 1;i >= 0;i --){
                            A.push_back(a[i]-'0');
                        }
                        for(int i = b.size() - 1;i >= 0;i --){
                            B.push_back(b[i]-'0');
                        }
                        if(cmp(A,B)){
                            auto C = sub(A,B);
                            for(int i = C.size() - 1; i >= 0;i --){
                            cout 
                            auto C = sub(B,A);
                            cout 
                            cout 
                        ios::sync_with_stdio(false);
                        cin.tie(NULL),cout.tie(NULL);
                        int t = 1;
                        //cint;
                        while(t--){
                            solve();
                        }
                        return 0 ;
                    }
                    

                    高精乘低精(https://www.acwing.com/activity/content/problem/content/827/)

                    #include
                    #define int long long
                    typedef long long ll;
                    using namespace std;
                    const int N = 1e5 + 10;
                    const int mod  = 1e9 + 7;
                    vector mul(vector &A,int b)  // C = A*b
                    {
                        vectorC;
                        int t = 0;  //进位
                        for (int i = 0; i 1 && C.back() == 0) C.pop_back();    //去除前导零
                        return C;
                    }
                    void solve(){
                        string a;
                        int b;
                        cin>>a>>b;
                        vector A;
                        for(int i = a.size() - 1;i >= 0;i --){
                            A.push_back(a[i]-'0');
                        }
                        auto C = mul(A,b);
                        for(int i = C.size() - 1; i >= 0;i --){
                            cout 
                        ios::sync_with_stdio(false);
                        cin.tie(NULL),cout.tie(NULL);
                        int t = 1;
                        //cin>t;
                        while(t--){
                            solve();
                        }
                        return 0 ;
                    }
                    

                    高精度除法(https://www.acwing.com/problem/content/796/)

                    高精除以低精

                    #include
                    #define int long long
                    typedef long long ll;
                    using namespace std;
                    const int N = 1e5 + 10;
                    const int mod  = 1e9 + 7;
                    vector div(vector &A,int b,int &r)  // C = A/b ,r为余数
                    {
                        vectorC;
                        r = 0;  //余数
                        for (int i = A.size()-1; i >= 0; i -- ){
                            r = r*10 + A[i];
                            C.push_back(r/b);
                            r%=b;
                        }
                        reverse(C.begin(),C.end());
                        while(C.size()>1 && C.back() == 0) C.pop_back();    //去除前导零
                        return C;
                    }
                    void solve(){
                        string a;
                        int b;
                        cin>>a>>b;
                        vector A;
                        for(int i = a.size() - 1;i >= 0;i --){
                            A.push_back(a[i]-'0');
                        }
                        int r;
                        auto C = div(A,b,r);
                        for(int i = C.size() - 1; i >= 0;i --){
                            cout 
                        ios::sync_with_stdio(false);
                        cin.tie(NULL),cout.tie(NULL);
                        int t = 1;
                        //cint;
                        while(t--){
                            solve();
                        }
                        return 0 ;
                    }
                    
                        if(x >w[i];
                        }
                        //dp[i]背包容量为i的最大价值
                        //需要注意的是一维度需要逆序更新,因为正序更新
                        //对于第i个,可能由i-2转移,却还是使用的i-1转移,所以逆序
                        for (int i = 1; i       //枚举物品
                            for (int j = m; j = v[i]; --j) {   //从大容积向小容积枚举,注意j小于v[i]就不必更新
                                dp[j] = max(dp[j],dp[j - v[i]] + w[i]);     //更新最大价值
                            }
                        }
                        cout
                        cinn>>m;
                        for (int i = 1; i 
                            cin>v[i]>>w[i];
                        }
                        //dp[i][j]代表i个物品,背包容量为j的最大价值
                        for (int i = 1; i 
                            //枚举容量,最大容量为m
                            for (int j = 0; j    //注意与01背包的差别,01背包是倒序
                                //优化可以去掉k层循环
                                dp[i][j] = dp[i-1][j];
                                if(j = v[i]){
                                    dp[i][j] = max(dp[i][j],dp[i][j-v[i]] + w[i]);//注意与01背包的差别,01背包是与dp[i-1][j - v[i]] + w[i]比
                                }
                            }
                        }
                        cout
                        cinn>m;
                        for (int i = 1; i 
                            cin>v[i]>>w[i];
                        }
                        //dp[i]代表背包容量为i的最大价值
                        for (int i = 1; i 
                            //枚举容量,最大容量为m
                            for (int j = v[i]; j    //注意与01背包的差别,01背包是倒序
                                dp[j] = max(dp[j],dp[j - v[i]] + w[i]); //注意与01背包区分
                            }
                        }
                        cout   //注意数组的大小不要开小了
                        int v,w,s;
                        int t = 0;  //跟新数组下标,把n个物品全都放到一个数组中
                        cinnm;
                        while (n--){
                            cin>>v>>w>>s;
                            while (s--){
                                a[++t] = v;
                                b[t] = w;
                            }   //拆开,把多重背包拆成一个背包;
                        }
                        for (int i = 1; i   //01背包模板
                            for (int j = m; j = a[i]; --j) {
                                dp[j] = max(dp[j],dp[j-a[i]] + b[i]);
                            }
                        }
                        cout   //注意数组的大小不要开小了
                        cinn>>m;
                        int cnt = 0;    //分组的类别
                        for (int i = 1; i 
                            int a,b,s;
                            cin>a>>b>>s;
                            int k = 1;  //每个组的个数
                            while (k 
                                cnt++;
                                v[cnt] = a*k;   //整体体积
                                w[cnt] = b*k;   //整体价值
                                s -= k; //s要减小
                                k *= 2;
                            }
                            if(s  0){
                                cnt ++;
                                v[cnt]  = a*s;
                                w[cnt] = b*s;
                            }
                        }
                        n = cnt;
                        //01背包模板
                        for (int i = 1; i 
                            for (int j = m; j = v[i]; --j) {
                                dp[j] = max(dp[j],dp[j-v[i]] + w[i]);
                            }
                        }
                        cout   //注意数组的大小不要开小了
                        cinnm;
                        for (int i = 1; i 
                            cin>v[i]>>w[i]>>s[i];
                        }
                        for (int i = 1; i 
                            memcpy(g,dp,sizeof g);
                            for (int r = 0; r s;
                            if(s == -1){
                                s = 1;
                            } else if(s == 0){
                                s = m/a;    //若为完全背包,则在最优情况下,只能取总体积/该物品体积向下取整
                            }
                            int k = 1;  //计算当前物品分为0,2,4,6.....
                            while (k  //多重背包转化为01背包,二进制优化转化过程
                                v[cnt] = a*k;
                                w[cnt] = b*k;
                                s -= k;
                                k *= 2;
                                cnt++;
                            }
                            if(s  0){  //计算剩下的一部分
                                v[cnt] = a*s;
                                w[cnt] = b*s;
                                cnt++;
                            }
                        }
                        //01背包模版
                        for (int i = 1; i 
                            for (int j = m; j = v[i]; --j) {
                                dp[j] = max(dp[j],dp[j - v[i]] + w[i]);
                            }
                        }
                        cout   //注意数组的大小不要开小了
                        cinnm;
                        for (int i = 1; i 
                            cin>s[i];
                            for (int j = 1; j 
                                cin>v[i][j]>>w[i][j];
                            }
                        }
                        //模仿01背包的写法;
                    /*    for (int i = 1; i 
                            for (int j = m; j = 0; --j) {  //从大体积向小体积枚举
                                for (int k = 1; k 
                                    if(j = v[i][k]) dp[j] = max(dp[j],dp[j-v[i][k]] + w[i][k]);
                                }
                            }
                        }
                        cout   //注意数组的大小不要开小了
                        cinnmz;
                        for (int i = 1; i 
                            cin>v[i]>>x[i]>>w[i];
                        }
                        //类似01背包,在循环里面再多加一层循环
                        for (int i = 1; i 
                            for (int j = m; j = v[i]; --j) {
                                for (int k = z; k >= x[i]; --k) {
                                    dp[j][k] = max(dp[j][k],dp[j - v[i]][k - x[i]] + w[i]);
                                }
                            }
                        }
                        cout   //注意数组的大小不要开小了
                        cinnm;
                        for (int i = 1; i 
                            cin>v[i]>>w[i];
                        }
                        //先初始化,初始什么也不装为1;
                        for (int i = 0; i 
                            cnt[i] = 1;
                        }
                        for (int i = 1; i 
                            for (int j = m; j = v[i]; --j) {
                                int value = dp[j-v[i]] + w[i];
                                if(value  dp[j]){  //如果转移的话,cnt也跟着转移
                                    dp[j] = value;
                                    cnt[j] = cnt[j - v[i]];
                                }else if(value == dp[j]){   //相等的话,cnt[j] += cnt[j-v[i]]
                                    cnt[j] = (cnt[j] + cnt[j-v[i]])%mod;
                                }
                            }
                        }
                        cout   //注意数组的大小不要开小了
                        cinnm;
                        for (int i = 1; i 
                            cin>v[i]>>w[i];
                        }
                        /*
                         * 01背包模版求最大价值
                         * 不同的是要求输出字典序最小的方案,所以我们求最大价值应当倒序
                         */
                        for (int i = n; i >= 1; --i) {
                            for (int j = 0; j 
                                dp[i][j] = dp[i+1][j];
                                if(j = v[i]){
                                    dp[i][j] = max(dp[i][j],dp[i+1][j - v[i]] + w[i]);
                                }
                            }
                        }
                        /**
                         * 正序求路径
                         */
                        for (int i = 1,j = m; i 
                            if(j = v[i] && dp[i][j] == dp[i+1][j-v[i]] + w[i]){
                                path.push_back(i);
                                j -= v[i];
                            }
                        }
                        for (int i = 0; i w[i];
                        }
                        for (int i = 1; i 
                            for (int j = m; j = v[i]; --j) {
                                dp[j] = max(dp[j-v[i]] + w[i],dp[j]);
                            }
                        }
                        cout
                            for (int j = m; j = v[i]; --j) {
                                dp[j] = max(dp[j-v[i]] + w[i],dp[j]);
                            }
                        }
                        if(dp[m] 
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]