プロジェクトオイラー問158

http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%20158
Problem 158 「左隣の文字より辞書順で後になる文字がちょうど1個となる文字列の探査」 †
26文字のアルファベットから3個の異なった文字を取ると, 長さ3の文字列を作ることができる.
例えば, 'abc', 'hat', 'zyx'となる.
この3つの例について調べると, 'abc'は左隣の文字より辞書順で後になる文字が2個ある.
'hat'では, 左隣の文字より辞書順で後になる文字がちょうど1個となり, 'zyx'では0個となる.
左隣の文字より辞書順で後になる文字がちょうど1個となるような長さ3の文字列は全部で10400個存在する.

いま, n ≤ 26 個の異なったアルファベットからなる文字列について考える.
nについて, p(n) を左隣の文字より辞書順で後になる文字がちょうど1個となるような長さnの文字列の個数であるとする.

p(n) の最大値を求めよ.





プロジェクトオイラーで頻出のワンパターン問題、漸化式が立てば一発で解けるタイプです。
漸化式立てるのに30分くらい悩みました。



#include<stdio.h>
#include<iostream>
#include<string.h>

int main(){
	__int64 dp[2][26][26];
	memset(dp,0,sizeof(dp));
	for(int i=0;i<26;i++){
		dp[0][0][i]=1;
	}
	__int64 ans=0;
	for(int i=1;i<26;i++){
 		__int64 sum=0;
		for(int j=25;j>=0;j--){
			for(int k=j-1;k>=0;k--){
				dp[0][i][k]+=dp[0][i-1][j];
 				dp[1][i][k]+=dp[1][i-1][j];
			}
		}
		for(int j=0;j<26-i;j++){
			for(int k=0;k<=j;k++){
				dp[1][i][j]+=dp[0][i-1][k];
			}
		}
		for(int j=0;j<26;j++){
			sum+=dp[1][i][j];
		}
		std::cout<<sum<<"\n";
		if(sum>ans)ans=sum;
	}
	std::cout<<"ans="<<ans<<"\n";
}
最終更新:2016年02月05日 13:42