牛客網多校第一場 E Removal DP

2021-08-27 03:28:19 字數 1813 閱讀 8505

題目大意:乙個長度為n的陣列,問其刪除了m個字元後,所有不同的子串有多少個

首先我們來看看這個題目的簡化版:

51 nod 1202 子串行個數

題目很裸,就是問乙個陣列子串行的個數

我們用dp來解決這個問題,dp[i]表示前i個字元能夠組成多少個不同的子串行

首先每次對於乙個數的加入

如果這個數沒有在前面出現過

如果我們選擇這個數,顯然這個數可以和前面所有的子串行組成乙個新的子串行

所以dp[i]=2*dp[i-1]

如果這個數在前面出現過,首先我們找到距離其最近出現的位置pos

對於選擇了這個數的情況

比如:1 2 3 4 5 6 7 5

這個時候5不能和前面所有子串行組成乙個新的子串行

對於pos位置之前所有的不同的子串行,和這個數字組成的所有子串行都已經通過pos位置那個相同的數算了一遍

所以我們這裡要減去重複的數

dp[i]=2*dp[i]-dp[pos]

#include #include #include #include using namespace std;

typedef long long llt;

const int mod=1e9+7;

const int maxn=111111;

int arr[maxn];

int last[maxn];

llt dp[maxn];

int main()

else dp[i]=2*dp[i-1]%mod;

last[val]=i;

}printf("%lld\n",dp[n]-1);

}return 0;

}

然後我們回到正題,對於這個題目來說,解題思路和上面那個題目差不多,但是這個題目多了乙個長度的限制

我們用dp[i][j]表示前i個數字,刪除了j個字元,最多能組成多少個不同的子串行

情況和前面類似,如果這個數字沒有在前面出現過,那麼對於這個數字我們可以選擇刪或者不刪

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

如果這個數字在前面出現過,那麼我們找到距離其最近的位置

首先因為dp[i][j]表示在前i個字串刪除了j個字元,也就是說取了(i-j)個數

如果我們這裡選擇了這個數,也就是說在前i-1個位置裡面取了(i-1-j)個數

這裡和之重複的部分是選擇了這個字元出現的上乙個位置,並且在前(last[val]-1)個位置選擇了(i-1-j)個數

也就是說在前(last[val]-1)個數中刪除了(last[val]-1)-(i-1-j)個數

所以這裡dp[i][j]=dp[i-1][j-1]+dp[i-1]][j]+dp[last[val]-1][(last[val]-1)-(i-1-j)]

附上**~~

#include #include #include #include using namespace std;

//題目問的是長度為k的字串刪除了k個子串後

//存在多少個互不相同的子串行

typedef long long llt;

const int mod=1e9+7;

const int size=1e5+111;

int arr[size];

llt dp[size][11];

int last[15];

int main()

}last[val]=i;

}printf("%lld\n",dp[n][m]);

}return 0;

}

牛客寒假多校第一場A

題目描述 在絕地求生 吃雞 遊戲裡,不同的槍枝有不同的威力,更是可以搭配不同的配件,以提公升槍枝的效能。每一把槍都有其威力及其可裝備配件種類。每乙個配件有其所屬種類,可以為槍枝提供威力的百分比加成。每一把槍只能裝備乙個同類配件。給你n把槍枝和m個配件,槍的威力為p,可裝備的配件數量為k,為k個不同型...

牛客多校第一場 B Inergratiion

傳送門 給你乙個 根據線代的知識 我們可以將分母裂項,然後根據 int fracdx frac int frac 2 d frac frac 可以推得 我們的答案就是裂項後求出來的係數乘上 frac 詳情請看d神推導吧 include include include include include ...

2020 牛客多校第一場

a b suffix array f infinite string comparision jzk開場提出了兩倍最大的長度,然後 dh 說直接比較a b和b a即可,由於是訓練賽,不想寫太長的 然後交了一發直接比較的 就過了 includeusing namespace std string s1...