2011/03/27

AAAABBBBAAAABBB

2つの文字 A, B を使って作られる長さ 15 の順列のうち次の条件を満たすものは何個あるか.
条件: 「連続する2文字の (順序) 対として AA が 5 回, AB, BA, BB が各 3 回現れる.」
例えば順列 AABBAAAABAABBBB は, AA が 5 回, AB が 3 回, BA が 2回, BB が 4 回現れるので, 上の条件を満たしていない.
1991年数オリ予選より


解けなかったので、悔しいから(&ヒマだから)プログラムで。

解答の方針はA→B、B→Aと変わる所に注目して、
ABとBAが3回出現するから
Aの”カタマリ”をa,Bのカタマリをbとすると、有り得るのは
abababa
または
bababab
の2つの場合。
両方を数え上げればおk(980通り)

細かい解説は多分どこかにあるんで検索してください。

んで、一般化したときに(上の条件はAとBだけで、4パターン全て出てる。ABCで作った列で、AB,ACが1回ずつある時のみカウントとか)力技以外で解く方法とかあるのかにゃ?


#include 
#include 

int N=15;

int chk(int a[]){
 
 int cntAA=0;
 int cntBB=0;
 int cntBA=0;
 int cntAB=0;
 
 for(int i=1;i<=N-1;i++){
  
  if(a[i]==0 && a[i+1]==0)
   cntAA++;
   
  if(a[i]==0 && a[i+1]==1)
   cntAB++;
  
  if(a[i]==1 && a[i+1]==0)
   cntBA++;
  
  if(a[i]==1 && a[i+1]==1)
   cntBB++;
  
 }

 
 if(cntAA==5 && cntAB==3 && cntBA==3 && cntBB==3){
  
  return 1;
 
 }else{
  
  return 0;
  
 }
 
}
 
 

int main(void)
{

 int a[N+1];
 int count=0;
 
 int MAX=pow(2,15)-1;

 for(int n=0;n<=MAX;n++){
  
  //10進数→2進数
  for(int i=1;i<=N;i++)
   a[i]=(n/(int)pow(2,i-1))%2;
  
 
  if(chk(a))count++;
  
 }

 printf("%d",count);
 
 return 0;
}