• 【开坑】codeforces水题泛做


    关于一些水题,思维题,套路dp菜得不行,于是点了个dp-tag,开了这个坑

    目前困于水平只限制了1k4到1k8分数段的题,按过题人数降序,1k6+就很虐我了估计放开上限到2k+就受不了了QAQ

    由于cf的tag机制,混了一些奇怪的东西不太像dp的题进来,能练手的也尽量写了

    总之,为了队友,为了湘潭邀请赛和女生赛,赶紧提高到能独立完成gym3x的程度吧(还是太菜了QAQ

    455A - 删a[k]会删除所有a[k]-1和a[k]+1,获得a[k]

    dp[i]为数字1-i能获得的最大价值

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #define LL long long
     6 #define INF 0x3f3f3f3f
     7 #define debug(x) cout << #x << " = " << x << endl;
     8 using namespace std;
     9 
    10 const int mx = 1e5;
    11 LL dp[mx+7];
    12 int vis[mx+10];
    13 
    14 int main(){
    15     int n, a, m = 0;
    16     scanf("%d", &n);
    17     for (int i = 1; i <= n; i++) {
    18         scanf("%d", &a);
    19         m = max(m, a);
    20         vis[a]++;
    21     }
    22     dp[1] = vis[1];
    23     for (int i = 2; i <= m; i++){
    24         dp[i] = max(dp[i-1], dp[i-2]+1ll*vis[i]*i);
    25     }
    26     printf("%lld
    ", dp[m]);
    27     return 0;
    28 }
    View Code

    466C - 数组划分成相等三段的方案数

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #define LL long long
     7 #define INF 0x3f3f3f3f
     8 #define debug(x) cout << #x << " = " << x << endl;
     9 using namespace std;
    10 
    11 const int mx = 5e5+7;
    12 LL sum[mx];
    13 
    14 int main(){
    15     int n, c;
    16     scanf("%d", &n);
    17     for (int i = 1; i <= n; i++){
    18         scanf("%d", &c);
    19         sum[i] = sum[i-1]+c;
    20     }
    21     vector<int> a, b;
    22     for (int i = 1; i < n; i++){
    23         if (sum[i]*3 == sum[n]) a.push_back(i);
    24         if (sum[i]*3 == sum[n]*2) b.push_back(i);
    25     }
    26     LL ans = 0;
    27     for (int i = 0; i < a.size(); i++){
    28         int k = upper_bound(b.begin(), b.end(), a[i])-b.begin();
    29         ans += b.size()-k;
    30     }
    31     printf("%lld
    ", ans);
    32     return 0;
    33 }
    View Code

    698A - 每天能做事或者休息,两天不做一样的事,最小休息天数

    dp[i][0/1/2]当天做的事/休息

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #define LL long long
     6 #define INF 0x3f3f3f3f
     7 #define debug(x) cout << #x << " = " << x << endl;
     8 using namespace std;
     9 
    10 const int mx = 110;
    11 int dp[mx][3];
    12 
    13 int main(){
    14     int n, a;
    15     scanf("%d", &n);
    16     memset(dp, INF, sizeof dp);
    17     //dp[i][0/1/2]
    18     dp[0][0] = 0;
    19     for (int i = 1; i <= n; i++) {
    20         scanf("%d", &a);
    21         dp[i][0] = min(dp[i-1][0], min(dp[i-1][1], dp[i-1][2]))+1;
    22         if (!a) continue;
    23         if (a != 2) dp[i][2] = min(dp[i-1][0], dp[i-1][1]);
    24         if (a != 1) dp[i][1] = min(dp[i-1][0], dp[i-1][2]);
    25     }
    26     printf("%d
    ", min(dp[n][0], min(dp[n][1], dp[n][2])));
    27     return 0;
    28 }
    View Code

    545C - n棵树砍了往左或者往右倒,不能倒在一起,最大砍伐数

    dp[i][0/1]当前往左或者往右倒

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #define LL long long
     7 #define INF 0x3f3f3f3f
     8 #define debug(x) cout << #x << " = " << x << endl;
     9 using namespace std;
    10 
    11 const int mx = 1e5+7;
    12 LL x[mx], h[mx];
    13 int dp[mx][2];
    14 
    15 int main(){
    16     int n;
    17     scanf("%d", &n);
    18     for (int i = 1; i <= n; i++) scanf("%lld%lld", &x[i], &h[i]);
    19     dp[1][0] = 1, dp[1][1] = x[1]+h[1] < x[2];
    20     x[n+1] = 1e18;
    21     for (int i = 2; i <= n; i++){
    22         dp[i][0] = max(dp[i][0], dp[i-1][0]+(x[i]-h[i] > x[i-1]));
    23         dp[i][0] = max(dp[i][0], dp[i-1][1]+(x[i]-h[i] > x[i-1]+h[i-1]));
    24         dp[i][1] = max(dp[i][1], dp[i-1][1]+(x[i-1]+h[i-1] < x[i] && x[i]+h[i] < x[i+1]));
    25         dp[i][1] = max(dp[i][1], dp[i-1][0]+(x[i]+h[i] < x[i+1]));
    26     }
    27     printf("%d
    ", max(dp[n][0], dp[n][1]));
    28     return 0;
    29 }
    View Code

    431C - k叉树边权1-k,和为n且有一条不小于d的边权的路径数

    背包,dp[i][0/1]边权为i,最大值是否大于d

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #define LL long long
     7 #define INF 0x3f3f3f3f
     8 #define debug(x) cout << #x << " = " << x << endl;
     9 using namespace std;
    10 
    11 const int mx = 110;
    12 const int mod = 1e9+7;
    13 LL dp[mx][2];
    14 
    15 int main(){
    16     int n, k, d;
    17     scanf("%d%d%d", &n, &k, &d);
    18     //dp[w][0/1]
    19     dp[0][0] = 1;
    20     for (int i = 1; i <= n; i++){
    21         for (int j = 1; j <= k; j++){
    22             if (i < j) break;
    23             dp[i][1] += dp[i-j][1];
    24             dp[i][(j >= d)] += dp[i-j][0];
    25             dp[i][0] %= mod, dp[i][1] %= mod;
    26         }
    27     }
    28     printf("%lld
    ", dp[n][1]);
    29     return 0;
    30 }
    View Code

    474D - 只能吃1朵红花,或者k的倍数朵白花

    。。。居然跟选拔赛我出的题一模一样,背包

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #define LL long long
     6 #define INF 0x3f3f3f3f
     7 #define debug(x) cout << #x << " = " << x << endl;
     8 using namespace std;
     9 
    10 const int mx = 1e5+7;
    11 const int mod = 1e9+7;
    12 LL sum[mx], dp[mx];
    13 
    14 int main(){
    15     int t, k, a, b;
    16     scanf("%d%d", &t, &k);
    17     //dp[i] = dp[i-1]+dp[i-k]
    18     dp[0] = 1;
    19     for (int i = 1; i < k; i++) 
    20         dp[i] = 1, sum[i] = sum[i-1]+1;
    21     for (int i = k; i < mx; i++) 
    22         dp[i] = (dp[i-1]+dp[i-k])%mod, sum[i] = (sum[i-1]+dp[i])%mod;
    23     while (t--){
    24         scanf("%d%d", &a, &b);
    25         printf("%lld
    ", (sum[b]-sum[a-1]+mod)%mod);
    26     }
    27     return 0;
    28 }
    View Code

    414B - 构造1-n内长为k,后一个数是前一个数倍数的数组方案

    dp[i][j]表示前i个数最后一位放j

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #define LL long long
     7 #define INF 0x3f3f3f3f
     8 #define debug(x) cout << #x << " = " << x << endl;
     9 using namespace std;
    10 
    11 const int mx = 2010;
    12 const int mod = 1e9+7;
    13 LL dp[mx][mx];
    14 
    15 int main(){
    16     int n, k;
    17     scanf("%d%d", &n, &k);
    18     for (int i = 1; i <= n; i++) dp[1][i] = 1;
    19     for (int i = 2; i <= k; i++){
    20         for (int j = 1; j <= n; j++){
    21             for (int s = 1; s*s <= j; s++){
    22                 if (j % s != 0) continue;
    23                 dp[i][j] += dp[i-1][s];
    24                 if (s*s != j) dp[i][j] += dp[i-1][j/s];
    25                 dp[i][j] %= mod;
    26                 //cout << i << " " << j << " " << s << " " << dp[i][j] << endl;
    27             }
    28         }
    29     }
    30     LL ans = 0;
    31     for (int i = 1; i <= n; i++)
    32         ans = (ans + dp[k][i]) % mod;
    33     printf("%lld
    ", ans);
    34     return 0;
    35 }
    View Code

    166E - 四面体走n步回到原点的方案

    dp[i][j] 第i步在j点,16n滚动数组卡着时限过,有递推公式n解

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #define LL long long
     7 #define INF 0x3f3f3f3f
     8 #define debug(x) cout << #x << " = " << x << endl;
     9 using namespace std;
    10 
    11 const int mod = 1e9+7;
    12 LL dp[2][4];
    13 
    14 void upd(int c, int t){
    15     for (int i = 0; i < 4; i++){
    16         if (i == c) continue;
    17         dp[t^1][c] += dp[t][i];
    18         dp[t^1][c] %= mod;
    19     }
    20 }
    21 
    22 int main(){
    23     int n, t = 1;
    24     scanf("%d", &n);
    25     dp[1][0] = 1;
    26     for (int i = 1; i <= n; i++){
    27         for (int j = 0; j < 4; j++) upd(j, t);
    28         memset(dp[t], 0, sizeof dp[t]);
    29         t ^= 1;
    30     }
    31     printf("%lld
    ", dp[t][0]);
    32     return 0;
    33 }
    View Code

    706C - n个字符串可以反转,改成字典序的花费

    dp[i][0/1] 前i个字符串当前反/不反

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #define LL long long
     7 #define INF 0x3f3f3f3f3f3f3f3f
     8 #define debug(x) cout << #x << " = " << x << endl;
     9 using namespace std;
    10 
    11 const int mx = 1e5+7;
    12 struct node{
    13     int num;
    14     string a, b;
    15 }s[mx];
    16 LL dp[mx][2];
    17 
    18 int main(){
    19     int n;
    20     cin >> n;
    21     for (int i = 1; i <= n; i++) cin >> s[i].num;
    22     for (int i = 1; i <= n; i++){
    23         cin >> s[i].a;
    24         s[i].b.assign(s[i].a.rbegin(), s[i].a.rend());
    25         dp[i][0] = dp[i][1] = INF;
    26     }
    27     dp[1][0] = 0, dp[1][1] = s[1].num;
    28     for (int i = 2; i <= n; i++){
    29         if (s[i].a >= s[i-1].a) dp[i][0] = min(dp[i][0], dp[i-1][0]);
    30         if (s[i].a >= s[i-1].b) dp[i][0] = min(dp[i][0], dp[i-1][1]);
    31         if (s[i].b >= s[i-1].a) dp[i][1] = min(dp[i][1], dp[i-1][0]+s[i].num);
    32         if (s[i].b >= s[i-1].b) dp[i][1] = min(dp[i][1], dp[i-1][1]+s[i].num);
    33     }
    34     LL ans = min(dp[n][0], dp[n][1]);
    35     printf("%lld
    ", ans == INF ? -1 : ans);
    36     return 0;
    37 }
    View Code

    676C - 长度为n的ab字符串可以改k个字符,最长连续相同段

    前缀和,二分左端点

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #define LL long long
     7 #define INF 0x3f3f3f3f
     8 #define debug(x) cout << #x << " = " << x << endl;
     9 using namespace std;
    10 
    11 const int mx = 1e5+7;
    12 char s[mx];
    13 int sum[2][mx];
    14 
    15 int main(){
    16     int n, k;
    17     scanf("%d%d%s", &n, &k, s+1);
    18     for (int i = 1; i <= n; i++){
    19         sum[0][i] = sum[0][i-1]+(s[i] == 'a');
    20         sum[1][i] = sum[1][i-1]+(s[i] == 'b');
    21     }
    22     int ans = 0;
    23     for (int i = 1; i <= n; i++){
    24         int x = upper_bound(sum[0]+1, sum[0]+n+1, sum[0][i]+k-(s[i]=='a'))-sum[0]-1;
    25         ans = max(ans, x-i+1);
    26         x = upper_bound(sum[1]+1, sum[1]+n+1, sum[1][i]+k-(s[i]=='b'))-sum[1]-1;
    27         ans = max(ans, x-i+1);
    28     }
    29     printf("%d
    ", ans);
    30     return 0;
    31 }
    View Code

    446A - n个数能改变一个,求最长递增子串

    搞一下左边有多少比它小的,右边有多少比它大的枚举

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #define LL long long
     7 #define INF 0x3f3f3f3f
     8 #define debug(x) cout << #x << " = " << x << endl;
     9 using namespace std;
    10 
    11 const int mx = 1e5+7;
    12 int a[mx], l[mx], r[mx];
    13 
    14 int main(){
    15     int n;
    16     scanf("%d", &n);
    17     for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    18     if (n <= 2){
    19         printf("%d
    ", n);
    20         return 0;
    21     }
    22     for (int i = 2; i <= n; i++){
    23         if (a[i] > a[i-1]) l[i] = l[i-1]+1; 
    24         else l[i] = 0;
    25     }
    26     for (int i = n-1; i >= 1; i--) {
    27         if (a[i] < a[i+1]) r[i] = r[i+1]+1; 
    28         else r[i] = 0;
    29     }
    30     int ans = 0;
    31     ans = max(ans, l[n-1]+2);
    32     ans = max(ans, r[2]+2);
    33     for (int i = 2; i < n; i++){
    34         int sum = max(l[i-1], r[i+1]);
    35         if (a[i-1]+1 < a[i+1]) sum += min(l[i-1], r[i+1])+1;
    36         ans = max(ans, sum+2);
    37     }
    38     printf("%d
    ", ans);
    39     return 0;
    40 }
    View Code

    2019.3.14 先回去了,今天没发现很有收获的题,水题就必须每天多写几题吧

    467C - 用k个长度为m不重合的区间覆盖n的数组,求最大价值

    dp[i][j] 前i个数字用了j个区间

    Java课上皮了一下偷偷刷题,代码没啥区别

     1 import java.util.Scanner;
     2 
     3 public class Main {
     4     public static void main(String[] args){
     5         final int MX = 5010;
     6         Scanner sc = new Scanner(System.in);
     7         int n = sc.nextInt(), m = sc.nextInt(), k = sc.nextInt(), a;
     8         long[] sum = new long[MX];
     9         for (int i = 1; i <= n; i++){
    10             a = sc.nextInt();
    11             sum[i] = sum[i-1]+a;
    12         }
    13         long[][] dp = new long[MX][MX];
    14         for (int i = 1; i <= n; i++){
    15             for (int j = 1; j <= k; j++){
    16                 dp[i][j] = dp[i-1][j];
    17                 if (i >= m)
    18                     dp[i][j] = Math.max(dp[i][j], dp[i-m][j-1]+sum[i]-sum[i-m]);
    19             }
    20         }
    21         System.out.println(dp[n][k]);
    22     }
    23 }
    View Code

    118D - 1有n个,2有m个,1最多连续放a个,2最多连续放b个

    dp[i][j][0/1] 1有i个2有j个,最后一个是1/2的方案数,取模坑了一发。。

    一开始状态定义对了,后来某个地方写搓了让我误以为状态是错的。。。最近几题几乎都是无脑直觉定状态居然还一路对过来了qwq

    还是畏难情绪太严重,其实这些都是水题的。。。开上限到2k了

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #define LL long long
     7 #define INF 0x3f3f3f3f
     8 #define debug(x) cout << #x << " = " << x << endl;
     9 using namespace std;
    10 
    11 const int mod = 1e8;
    12 const int mx = 110;
    13 LL dp[mx][mx][2];
    14 
    15 int main(){
    16     int n, m, a, b;
    17     scanf("%d%d%d%d", &n, &m, &a, &b);
    18     for (int i = 0; i <= a; i++) dp[i][0][0] = 1;
    19     for (int i = 0; i <= b; i++) dp[0][i][1] = 1;
    20     for (int i = 1; i <= n; i++){
    21         for (int j = 1; j <= m; j++){
    22             for (int k = 1; k <= a && i-k >= 0; k++){
    23                 dp[i][j][0] += dp[i-k][j][1];
    24                 dp[i][j][0] %= mod;
    25             }
    26             for (int k = 1; k <= b && j-k >= 0; k++){
    27                 dp[i][j][1] += dp[i][j-k][0];
    28                 dp[i][j][1] %= mod;
    29             }
    30         }
    31     }
    32     printf("%lld
    ", (dp[n][m][0]+dp[n][m][1])%mod);
    33     return 0;
    34 }
    View Code

    788A - dp[i][0/1]表示选第i个数,是奇数/偶数项的最大值

     1 #include <bits/stdc++.h>
     2 #define LL long long
     3 #define INF 0x3f3f3f3f
     4 #define INFLL 0x3f3f3f3f3f3f3f3f
     5 #define debug(x) cout << #x << " = " << x << endl;
     6 #define lid id << 1
     7 #define rid id << 1 | 1
     8 using namespace std;
     9 
    10 const int mx = 1e5+7;
    11 int a[mx];
    12 LL dp[mx][2];
    13 
    14 int main(){
    15     int n;
    16     scanf("%d", &n);
    17     for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    18     for (int i = 1; i < n; i++) a[i] = abs(a[i]-a[i+1]);
    19     LL ans = 0;
    20     for (int i = 1; i < n; i++){
    21         dp[i][0] = max(dp[i][0], dp[i-1][1]+a[i]);
    22         dp[i][1] = max(dp[i][1], dp[i-1][0]-a[i]);
    23         ans = max(ans, max(dp[i][0], dp[i][1]));
    24     }
    25     printf("%lld
    ", ans);
    26     return 0;
    27 }
    View Code

    534B - 初速度,加速度和末速度求最大位移

    dp[i][j]第i时刻速度为j

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #define LL long long
     6 #define INF 0x3f3f3f3f
     7 #define debug(x) cout << #x << " = " << x << endl;
     8 using namespace std;
     9 
    10 const int mx = 110;
    11 int dp[mx][mx*10];
    12 
    13 int main(){
    14     int vl, vr, t, d;
    15     scanf("%d%d%d%d", &vl, &vr, &t, &d);
    16     //dp[i][j] = max(dp[i-1][k] + k)
    17     memset(dp, -1, sizeof dp);
    18     dp[1][vl] = vl;
    19     for (int i = 1; i <= t; i++){
    20         for (int j = 0; j <= 1000; j++){
    21             if (dp[i][j] == -1) continue;
    22             for (int k = max(0, j-d); k <= j+d; k++)
    23                 dp[i+1][k] = max(dp[i+1][k], dp[i][j]+k);
    24         }
    25     }
    26     printf("%d
    ", dp[t][vr]);
    27     return 0;
    28 }
    View Code

    567C - 公比为k的等比数列数量

    k定下来就可以map暴力搞

     1 #include <bits/stdc++.h>
     2 #define LL long long
     3 #define INF 0x3f3f3f3f
     4 #define INFLL 0x3f3f3f3f3f3f3f3f
     5 #define debug(x) cout << #x << " = " << x << endl;
     6 using namespace std;
     7 
     8 const int mx = 1e5+7;
     9 map<int, LL> dp[4];
    10 
    11 int main(){
    12     int n, k, a;
    13     scanf("%d%d", &n, &k);
    14     LL ans = 0;
    15     //dp[i][j]第i-1项,数字为j
    16     for (int i = 1; i <= n; i++){
    17         scanf("%d", &a);
    18         if (a % k == 0){
    19             ans += dp[2][a/k];
    20             dp[2][a] += dp[1][a/k];
    21         }
    22         dp[1][a]++;
    23     }
    24     printf("%lld
    ", ans);
    25     return 0;
    26 }
    View Code

    553A - 组合数 这里有个线性推逆元的方法

     1 #include <bits/stdc++.h>
     2 #define LL long long
     3 #define INF 0x3f3f3f3f
     4 #define INFLL 0x3f3f3f3f3f3f3f3f
     5 #define debug(x) cout << #x << " = " << x << endl;
     6 using namespace std;
     7 
     8 const int mod = 1e9+7;
     9 const int mx = 1e6;
    10 int a[1010];
    11 LL fac[mx+5], inv[mx+5];
    12 
    13 void init(){
    14     fac[0] = 1;
    15     for (int i = 1; i <= mx; i++) fac[i] = fac[i-1]*i%mod;
    16     inv[1] = 1;
    17     for (int i = 2; i <= mx; i++) inv[i] = mod-(mod/i)*inv[mod%i]%mod;
    18     inv[0] = 1;
    19     for (int i = 1; i <= mx; i++) inv[i] = inv[i]*inv[i-1]%mod;
    20 }
    21 
    22 LL C(int n, int m){
    23     return fac[n]*inv[m]%mod*inv[n-m]%mod;
    24 }
    25 
    26 int main(){
    27     init();
    28     int n, sum = 0;
    29     scanf("%d", &n);
    30     for (int i = 1; i <= n; i++) {
    31         scanf("%d", &a[i]);
    32         sum += a[i];
    33     }
    34     LL ans = 1;
    35     for (int i = n; i >= 1; i--){
    36         ans = ans*C(sum-1, a[i]-1)%mod;
    37         sum -= a[i];
    38     }
    39     printf("%lld
    ", ans);
    40     return 0;
    41 }
    View Code

    607A - dp[i]表示i后面的全部破坏,前面会被破坏的数量

     1 #include <bits/stdc++.h>
     2 #define LL long long
     3 #define INF 0x3f3f3f3f
     4 #define INFLL 0x3f3f3f3f3f3f3f3f
     5 #define debug(x) cout << #x << " = " << x << endl;
     6 using namespace std;
     7 
     8 const int mx = 1e5+7;
     9 struct node{
    10     int x, y;
    11     bool operator < (const node& c) const {
    12         return x < c.x;
    13     }
    14 }a[mx];
    15 int dp[mx];
    16 
    17 int main(){
    18     int n;
    19     scanf("%d", &n);
    20     for (int i = 1; i <= n; i++) {
    21         scanf("%d%d", &a[i].x, &a[i].y);
    22     }
    23     sort(a+1, a+n+1);
    24     int ans = INF;
    25     for (int i = 1; i <= n; i++){
    26         int k = lower_bound(a+1, a+n+1, node{a[i].x-a[i].y, 0})-a-1;
    27         dp[i] = dp[k]+i-k-1;
    28         ans = min(ans, dp[i]+n-i);
    29     }
    30     printf("%d
    ", ans);
    31     return 0;
    32 }
    View Code

    603A - dp[i][0/1/2][0/1]表示前i个字符翻转的状态为j数字为k时的最大长度

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <map>
     6 #define LL long long
     7 #define INF 0x3f3f3f3f
     8 #define debug(x) cout << #x << " = " << x << endl;
     9 using namespace std;
    10 
    11 const int mx = 1e5+7;
    12 char s[mx];
    13 int dp[mx][3][2];
    14 
    15 int main(){
    16     int n, ans = 0;
    17     scanf("%d%s", &n, s+1);
    18     for (int i = 1; i <= n; i++){
    19         int c = s[i]-'0';
    20         memcpy(dp[i], dp[i-1], sizeof dp[i]);
    21         for (int j = 0; j < 3; j++){
    22             for (int k = 0; k < 2; k++) {
    23                 if (k != c)
    24                     dp[i][j][c] = max(dp[i][j][c], dp[i-1][j][k]+1);
    25                 else if (j)
    26                     dp[i][j][k] = max(dp[i][j][k], dp[i-1][j-1][k]+1);
    27             }
    28         }
    29     }
    30     for (int i = 0; i < 3; i++)
    31         for (int j = 0; j < 2; j++)
    32             ans = max(ans, dp[n][i][j]);
    33     printf("%d
    ", ans);
    34     return 0;
    35 }
    View Code

    577B - 抽屉原理,然后就是n方的裸dp,滚动数组(感觉memcpy的方法真的好写

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #define LL long long
     6 #define INF 0x3f3f3f3f
     7 #define debug(x) cout << #x << " = " << x << endl;
     8 using namespace std;
     9 
    10 const int mx = 1e6+7;
    11 int dp[2][1010];
    12 int a[mx];
    13 
    14 int main(){
    15     int n, m;
    16     scanf("%d%d", &n, &m);
    17     for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    18     if (n >= m){
    19         printf("YES
    ");
    20         return 0;
    21     }
    22     for (int i = 1; i <= n; i++){
    23         for (int j = 0; j < m; j++) dp[1][j] = 0;
    24         dp[1][a[i]%m] = 1;
    25         for (int j = 0; j < m; j++){
    26             if (dp[1][0]) break;
    27             if (a[i] % m == j) continue;
    28             dp[1][j] = max(dp[0][j], dp[0][(j-a[i]%m+m)%m]);
    29         }
    30         memcpy(dp[0], dp[1], sizeof dp[0]);
    31     }
    32     printf("%s
    ", dp[0][0] ? "YES" : "NO");
    33     return 0;
    34 }
    View Code

    264B - 设dp[i]为结尾的数字质因数有i的最大长度(可以看做是对于每一位ai的质因数做LIS

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #define LL long long
     6 #define INF 0x3f3f3f3f
     7 #define debug(x) cout << #x << " = " << x << endl;
     8 using namespace std;
     9 
    10 const int mx = 1e5+7;
    11 int a[mx], prime[mx];
    12 int dp[mx];
    13 bool vis[mx];
    14 int tot = 0;
    15 
    16 void init(int n){
    17     vis[1] = 1;
    18     for (int i = 2; i <= n; i++){
    19         if (!vis[i]) prime[++tot] = i;
    20         for (int j = 1; j <= tot && 1ll*i*prime[j] <= n; j++){
    21             vis[i*prime[j]] = 1;
    22             if (i % prime[j] == 0) break;
    23         }
    24     }
    25 }
    26 
    27 int main(){
    28     init(100000);
    29     int n, x, ans = 0;
    30     scanf("%d", &n);
    31     for (int i = 1; i <= n; i++) {
    32         scanf("%d", &a[i]);
    33         if (n == 1){
    34             printf("1
    ");
    35             return 0;
    36         }
    37         x = a[i];
    38         int tmp = 0;
    39         for (int j = 1; j <= tot && j*j <= x; j++){
    40             if (x % prime[j] != 0) continue;
    41             while (x % prime[j] == 0) x /= prime[j];
    42             tmp = max(tmp, dp[prime[j]]+1);
    43         }
    44         if (x > 1) tmp = max(tmp, dp[x]+1);
    45         x = a[i];
    46         for (int j = 1; j <= tot && j*j <= x; j++){
    47             if (x % prime[j] != 0) continue;
    48             while (x % prime[j] == 0) x /= prime[j];
    49             dp[prime[j]] = tmp;
    50         }
    51         if (x > 1) dp[x] = tmp;
    52         ans = max(ans, tmp);
    53     }
    54     printf("%d
    ", ans);
    55     return 0;
    56 }
    View Code

    225B- dp[i][j][0/1]表示前i列前面连续了j列相同,当前列是0/1的最小代价, 预处理代价然后刷表, 最后在合法范围内找答案

     1 #include <bits/stdc++.h>
     2 #define INF 0x3f3f3f3f
     3 #define debug(x) cout << #x << " = " << x << endl;
     4 #define lid id << 1
     5 #define rid id << 1 | 1
     6 using namespace std;
     7 typedef long long LL;
     8 typedef pair<int,int> pii;
     9 typedef pair<double,double> pdd;
    10 
    11 const int mx = 1010;
    12 char s[mx];
    13 int a[mx], dp[mx][mx][2];
    14 
    15 int main(){
    16     int n, m, x, y;
    17     scanf("%d%d%d%d", &n, &m, &x, &y);
    18     for (int i = 1; i <= n; i++){
    19         scanf("%s", s+1);
    20         for (int j = 1; j <= m; j++)
    21             if (s[j] == '#') a[j]++;
    22     }
    23     memset(dp, INF, sizeof dp);
    24     dp[1][1][0] = a[1];
    25     dp[1][1][1] = n-a[1];
    26     for (int i = 1; i < m; i++){
    27         for (int j = 1; j <= y; j++){
    28             if (dp[i][j][0] != INF){
    29                 if (j >= x) dp[i+1][1][1] = min(dp[i+1][1][1], dp[i][j][0] + n-a[i+1]);
    30                 dp[i+1][j+1][0] = min(dp[i+1][j+1][0], dp[i][j][0] + a[i+1]);
    31             }
    32             if (dp[i][j][1] != INF){
    33                 if (j >= x) dp[i+1][1][0] = min(dp[i+1][1][0], dp[i][j][1] + a[i+1]);
    34                 dp[i+1][j+1][1] = min(dp[i+1][j+1][1], dp[i][j][1] + n-a[i+1]);
    35             }
    36         }
    37     }
    38     int ans = INF;
    39     for (int i = x; i <= y; i++){
    40         ans = min(ans, dp[m][i][0]);
    41         ans = min(ans, dp[m][i][1]);
    42     }
    43     printf("%d
    ", ans);
    44     return 0;
    45 }
    View Code
  • 相关阅读:
    spring-boot 速成(6) 整合disconf
    spring-boot 速成(5) profile区分环境
    dubbox REST服务使用fastjson替换jackson
    resteasy经验谈
    spring-boot 速成(4) 自定义配置
    spring-boot 速成(3) actuator
    idea 高级调试技巧
    spring-boot 速成(2) devtools之热部署及LiveReload
    bash编程之xargs实用技巧
    spring-boot 速成(1) helloworld
  • 原文地址:https://www.cnblogs.com/QAQorz/p/10533268.html
Copyright © 2020-2023  润新知