zoukankan      html  css  js  c++  java
  • PTA 团体程序设计天梯赛 L3-020 至多删三个字符

    $f[i][j]$表示到第$i$个字符,已经删去了$j$个字符的方案数。

    显然的转移:

    $f[i][j] = f[i - 1][j] + f[i - 1][j - 1]$

    但是这样会有重复,我们考虑什么情况会重复。

    比如说:'aabab'中的'bab',我们删去'ba',得到'aab',删去'ab'得到'aab',两者是相同的

    1 2 3 4 5

    a a b a b

    我们假设之前的每一位存的都是没有重复的方案数

    就刚才的情况,我们发现当我们递推到第$5$个位置的时候,删去第三位和第四位的'ba',但是保留着第五位的'b'

    那这种情况和递推到第$3$个位置的时候,保留着第$3$位的'd'是一样的

    即:

    $f[5][2] = f[2][0]$

    $f[5][3] = f[2][1]$

    减去这些重复情况,我们就能保证已经递推过来的情况中没有重复情况

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 1000010
     6 int n;
     7 char s[N];
     8 int pos[220];
     9 ll f[N][4];
    10 
    11 int main()
    12 {
    13     while (scanf("%s", s + 1) != EOF)
    14     {
    15         memset(pos, -1, sizeof pos);
    16         n = strlen(s + 1);
    17         f[0][0] = 1;
    18         for (int i = 1; i <= n; ++i)
    19         {
    20             int d = pos[s[i]];
    21             pos[s[i]] = i;
    22             f[i][0] = f[i][1] = 1;
    23             for (int j = 1; j < 4; ++j)
    24             {
    25                 f[i][j] += f[i - 1][j];
    26                 f[i][j + 1] = f[i - 1][j];
    27                 if (d != -1 && j - i + d >= 0)
    28                     f[i][j] -= f[d - 1][j - i + d];
    29             }
    30         }
    31         printf("%lld
    ", f[n][0] + f[n][1] + f[n][2] + f[n][3]);
    32     }
    33     return 0;
    34 }
    View Code
  • 相关阅读:
    1001. 害死人不偿命的(3n+1)猜想 (15)
    单链表排序
    简单插入排序
    简单选择排序
    C语言-随机数
    二分查找(折半查找)
    顺序查找-顺序查找-带哨兵查找
    队列-链表实现
    循环队列_数组实现
    队列-顺序存储-简单实现
  • 原文地址:https://www.cnblogs.com/Dup4/p/10584694.html
Copyright © 2011-2022 走看看