HDU 6942 CCPC Strings题解

HDU6942. CCPC Strings

题意:长度为n的只含有"C"或"P"的字符串共有2n个,问:这所有2n个字符串中含有多少个"CCPC"(每一个"CCPC"之间不能相互重叠,即"CCPCCPC"中只能算1个"CCPC")

分析:

假设所有长度为n的"CP"字符串中互不重叠的"CCPC"的个数为an

若认为可以相互重叠,可以通过计算贡献的方式进行计算

// 1. CCPC***...*****(只关注子串[1...4]的贡献)
// 2. *CCPC**...*****(只关注子串[2...5]的贡献)
// 3. **CCPC*...*****(只关注子串[3...6]的贡献)
// 4. ***CCPC...*****(只关注子串[4...7]的贡献)
// 5. ****CCP...*****(只关注子串[5...8]的贡献)
// 6. *****CC...*****(只关注子串[6...9]的贡献)
// .
// .
// .
//n-4. *******...CCPC*(只关注子串[n-4...n-1]的贡献)
//n-3. *******...*CCPC(只关注子串[n-3...n]的贡献)

"CCPC"有(n3)种摆法,剩下(n4)个字符随便选

答案即为(n3)2n4

然而,题目要求每一个"CCPC"之间不能相互重叠

可以发现

1,4发生重叠,2,5发生重叠,3,6发生重叠,...

和上面的计算方法一样

即"CCPCCPC"有(n6)种摆法,剩下(n7)个字符随便选

总共为(n6)2n7

减掉这些,发现减多了

减多了哪些?

1,4,7发生重叠,2,5,8发生重叠,3,6,9发生重叠,...

即"CCPCCPCCPC"有(n9)种摆法,剩下(n10)个字符随便选

总共为(n9)2n10

加上这些,发现加多了

加多了哪些?

……

以此类推,容斥原理

答案为an=i=1n3(1)i1(n3i)2n3i1

从而有这个

an3=i=1n33(1)i1(n33i)2n33i1=i=1n33(1)i1(n33i)2n33i1=i=1n31(1)i1(n3(i+1))2n3(i+1)1=i=2n3(1)i(n3i)2n3i1

所以zyf大佬送给我的递推式an=(n3)2n4an3是对的(干得漂亮)

然而这题到这还没完,题目条件1n109,线性递推搞不定

啊这,梦回高中

由于

an+an3=(n3)2n4

8an2n1+an32n4=n3

an2n1=bn,有

8bn+bn3=n38(bn19n)+bn319n+3=08(bn19n)+bn319(n3)13+3=08(bn19n+827)+bn319(n3)+827=0

bn19n+827=cn,有

cn=18cn3

a1=a2=a3=0cn=an2n119n+827

c1=527c2=227c3=127

所以

c3n=127(18)n1c3n+1=527(18)nc3n+2=227(18)n

an=2n1(cn+19n827)

a3n=154(8(1)n+(9n8)8n)a3n+1=127(5(1)n+(9n5)8n)a3n+2=227(2(1)n+(9n2)8n)

代码:

#include <cstdio>
typedef long long Lint;
const Lint mod = 1e9 + 7;
Lint fpow(Lint a, Lint n) {
Lint res = 1;
for (; n; n >>= 1) {
if (n & 1) res = res * a % mod;
a = a * a % mod;
}
return res;
}
Lint minv(Lint a) { return fpow(a, mod - 2); }
Lint ainv(Lint a) { return mod - a; }
Lint mod_add(Lint a, Lint b) { return (a + b) % mod; }
Lint mod_mul(Lint a, Lint b) { return a * b % mod; }
Lint kn1n(Lint k, Lint n) { return n % 2 ? ainv(k) : k; }
const Lint inv1 = minv(54);
const Lint inv2 = minv(27);
const Lint inv3 = mod_mul(2, inv2);
int main() {
int T;
scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
int r = n % 3, k = n / 3;
Lint res = 0;
if (r == 0) {
res = mod_mul(inv1, mod_add(kn1n(8, k), mod_mul(mod_add(mod_mul(9, k), ainv(8)), fpow(8, k))));
} else if (r == 1) {
res = mod_mul(inv2, mod_add(kn1n(5, k), mod_mul(mod_add(mod_mul(9, k), ainv(5)), fpow(8, k))));
} else {
res = mod_mul(inv3, mod_add(kn1n(2, k), mod_mul(mod_add(mod_mul(9, k), ainv(2)), fpow(8, k))));
}
printf("%lld\n", res);
}
return 0;
}

本文作者:聆竹听风

本文链接:https://www.cnblogs.com/Bamboo-Wind/p/15028559.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   聆竹听风  阅读(332)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起