計蒜之道2018 複賽 G(排列組合)

2022-05-07 12:09:11 字數 1782 閱讀 6325

思路:沒注意串的大小有1e5,寫了發列舉並線性匹配發現超時了。這種問題往往要逆推!題目讓我們考慮str的去重全排列串中pattern的匹配次數,我們可以發現,只要str中有pattern的字母,那麼,str在排列的過程中至少會出現1次的pattern。於是,根據乘法分步原理,我們優先把str中湊成pattern的字母篩掉,剩餘字母進行全排列,假設剩餘字母位len,那麼這些字母會出現len+1個空位,利用插空法把pattern插入到這些空位中。同時,要對排列數進行去重,根據排除法依次算出每個字母的數量,分別除以這些數字的階乘即可。

列舉+線性匹配(超時)

#includeusing namespace std;

char str[100005], res[100005], pattern[100005];

int vis[100005], prefix[100005];

int len1, len2, cnt;

void get_prefix_table (int n) else

}}int kmp_search (int n, int m) else

if(j == m)

}return ans;}

void dfs(int idx)

int i, j;

for (i = 0; i < len1; i++)

if (j == len1)

}}}

int main()

return 0;

}

排列+逆元

#include using namespace std;

#define repu(i, a, b) for (int i = a; i <= b; i++)

#define repd(i, a, b) for (int i = a; i >= b; i--)

#define fast_io ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

#define ll long long

#define ldb long double

#define mo 1000000007

const int maxn = (int)1e5+5;

int t;

int vist[26];

char str[maxn], pattern[maxn];

ll inv(ll a)

return ans;

}ll calc(ll a)

int main()

vist[pattern[i] - 'a']--;

} if (flag) continue;

len1 -= len2; //扣除掉pattern的剩餘字母進行去重全排列,最後把pattern通過插空的策略還原

ll ans = 1;

repu(i, 0, 25)

cout << ( ( calc(len1) * inv(ans) ) % mo ) * (len1 + 1) % mo << endl;

} return 0;

}

計蒜之道複賽 B D F

b題是乙個簡單的模擬 求一下兩個點中間每過deta的整數點 然後更新一下每個點的最後一次經過就好了 1 include2 define cl a,b memset a,b,sizeof a 3 define debug x cerr x x 4 using namespace std 56 cons...

貝殼找房魔法師顧問 2018 計蒜之道 複賽

v v無向圖 強連通圖 每個子圖,n個點,選擇n 1條,使互相連線 因為目標點x 點y,可以改為點y 點x v c弱連通圖 將有向圖的所有的有向邊替換為無向邊,所得到的圖稱為原圖的基圖。如果乙個有向圖的基圖是連通圖,則有向圖是弱連通圖。1.乙個弱連通子圖,它裡面的點與該弱連通子圖外的點與沒有關係,可...

2019 計蒜之道 複賽 D 「星雲系統」

現在給定你乙個字串s以及乙個整數k,請求出s的字典序最小的長度為k的子串行。題目鏈結 第一行乙個由小寫英文本母構成的字串s,第二行乙個正整數k。一行乙個字串ans,表示答案。0helloworld 5ellld 設串長為n,則只需刪掉n k個字元。用乙個單調棧維護,依次將字串的每個字元插入,如果當前...