标签:子集 lower bsp namespace iostream 推导 不能 using i+1
链接:http://acm.uestc.edu.cn/#/problem/show/1587
题意:失恋772002天
给定一个整数N,对一个仅有三种字符组成的长度为N的字符串,问有多少种排列满足 任意三个连续的字符x,y,z中,x=y或者x=z或者y=z成立(也就是三个不能不同)
得到结果要取模后输出
题解:
水题0。0 ( 啪 x )
显然n=1的时候结果为3
假设S(n)表示长度为n(n>1)的所有满足题意的字符串的集合,那么我构造两个子集(划分):
S1(n):S中的字符串里最后两个字符不一样的字符串组成的集合
S2(n):S中的字符串里最后两个字符一样的字符串组成的集合
显然S1(n)与S2(n)不相交,而且S(n)等于S1(n)并上S2(n)
记D(n)为S1(n)的元素个数,A(n)为S2(n)的元素个数
那么我们可以知道,当n>2时
S(n-1)中的字符串同样也可以划分为S1(n-1)和S2(n-1):
1.对于S1(n-1)中的字符串:
1.1添加跟倒数第二个字符一样的那个字符可以变成S1(n)中的字符串
1.2添加跟最后一个字符一样的那个字符可以变成S2(n)中的字符串
2.对于S2(n-1)中的字符串:
2.1添加跟后面那个字符不一样的那个字符可以变成S1(n)中的字符串(每个字符串都有两种添加的选择)
2.2添加跟后面那个字符一样的那个字符可以变成S2(n)中的字符串
由1.1和2.1,有D(n) = D(n-1) + 2*A(n-1) (n>2)
由1.2和2.2,有A(n) = D(n-1) + A(n-1) (n>2)
而 D(2) = 6,A(2) = 3
为此,得到了递推式,最后结果为
3 (n=1)
D(n)+A(n) (n>=2)
其实对于上面那两个式子可以根据递推关系推导出只跟n有关的关系式,不过我懒得了(x)
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
#include<iostream>
#include<string>
#include<sstream>
//stringstream ss(line)
#include<algorithm>
//sort(a,a+n,cmp)
//p=lower_bound(a,a+n,x)-a+1(大于或等于x的第一个位置)
#include<vector>
#include<bitset>
//bitset<N> xx
using namespace std;
const int MOD = 554056561;
int main(){
int N;
scanf("%d",&N);
int D[2],A[2];
if(N==1) printf("%d",3);
else if(N==2) printf("%d",9);
else{
D[0]=6,A[0]=3;
for(int i=3;i<=N;i++){
A[i%2]=(A[(i+1)%2]+D[(i+1)%2])%MOD;
D[i%2]=(2*A[(i+1)%2]+D[(i+1)%2])%MOD;
}
printf("%d",(A[N%2]+D[N%2])%MOD);
}
return 0;
}
标签:子集 lower bsp namespace iostream 推导 不能 using i+1
原文地址:http://www.cnblogs.com/scidylanpno/p/6759707.html