CF 1065 E. Side Transmutations
阿新 • • 發佈:2018-10-14
ont return 有一個 不可 字符串翻轉 ostream ref http 也不會
E. Side Transmutations
http://codeforces.com/contest/1065/problem/E
題意:
長度為n的字符串,字符集為A,問多少不同的字符串。兩個字符串相同:
- 在給定的數組b中,找到一個數b[i],設k=b[i]
- 將1~k,與n-k+1~n 的字符串翻轉,然後交換位置。新形成的字符串與原來的字符串相等。
分析:
考慮只有一個b[i]的影響,那麽對於一個字符串,分成了三段,前面k個,後面k個,中間的。中間的部分就是$A^{n-k-k}$,再看兩邊形成多少種字符串,使得這些都是不同的。
左邊k個和右邊k個的所有的字符串,兩兩組合,加上中間的部分,構成一個字符串。然後這個字符串與操作後的字符串是相等的,於是它們應該只計算一次,所以除以2就行。但是有一些字符串操作後,與原來一樣,這些也不會形成等價的字符串,所以不需除以2,算一次就行了。
左邊k個的總方案數$A^{k}$,兩邊兩兩組合$A^{k+k}$。操作後與原來一樣的字符串$A^{k}$,表示左邊k個隨便選,右邊的k個為左邊的倒置。那麽第一部分就是$\frac{A^{k+k}-A^{k}}{2}$,再加上第二部分$A^{k}$,合並後$\frac{A^{k} \times (A^{k} + 1)}{2}$。
然後考慮增加一個b的影響,那麽中間的部分,不可以在按上一個的選了,為$A^{n-k-k}$,所以先不考慮中間的,只考慮兩邊的。因為b[i]下一個回事兩邊增加b[i+1]-b[i]個字符。那麽這b[i]在按照上面的方式組合,就會有形成一些新的字符串。那麽乘上這些即可,最後再乘上中間的部分。就是$A^{n-b[m]-b[m]}$
代碼:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<cctype> 7 #include<set> 8 #include<vector> 9 #include<queue> 10 #include<map> 11 #define fi(s) freopen(s,"r",stdin); 12#define fo(s) freopen(s,"w",stdout); 13 using namespace std; 14 typedef long long LL; 15 16 inline int read() { 17 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1; 18 for(;isdigit(ch);ch=getchar())x=x*10+ch-‘0‘;return x*f; 19 } 20 21 const int N = 200005; 22 const LL mod = 998244353; 23 24 LL ksm(LL a, LL b) { 25 LL res = 1; 26 while (b) { 27 if (b & 1) res = res * a % mod; 28 a = a * a % mod; 29 b >>= 1; 30 } 31 return res; 32 } 33 34 LL b[N]; 35 36 int main() { 37 int n = read(), m = read(); 38 LL A = read(); 39 for (int i=1; i<=m; ++i) b[i] = read(); 40 LL ans = 1, inv2 = ksm(2, mod - 2); 41 for (int i=1; i<=m; ++i) { 42 LL L = b[i] - b[i - 1]; 43 LL tmp = ksm(A, L); 44 ans = ans * tmp % mod * (tmp + 1) % mod; 45 ans = ans * inv2 % mod; 46 } 47 ans = ans * ksm(A, n - b[m] - b[m]) % mod; 48 cout << ans; 49 return 0; 50 }
CF 1065 E. Side Transmutations