Avoid K Palindrome 2

https://atcoder.jp/contests/abc363/editorial/10481 によると、next_permutationを使うのが想定とのこと。

なんと [**私は28言語でnext_permutationを実装しています。**](https://qiita.com/cielavenir/items/ac96da5e3040c2edb78c)

## Lua

現時点で私しかACしていません。

![スクリーンショット 2024-07-22 0.32.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29692/53c43e33-9133-dbd2-73cf-b57c745e2df3.png)

https://atcoder.jp/contests/abc363/submissions/55862042

```lua
#!/usr/bin/lua
reverse=function(a,start,size)
	local end_=start+size-1
	for i=0,size/2-1 do
		z=a[start+i]
		a[start+i]=a[end_-i]
		a[end_-i]=z
	end
end
next_permutation=function(a,n)
	if not n then n=#a end
	if n<0 or #a<n then
		return false
	end
	local i=0
	reverse(a,n,#a+1-n)
	i=#a-1
	while i>=1 do
		if a[i]<a[i+1] then break end
		i=i-1
	end
	if i<1 then
		reverse(a,1,#a)
		return false
	end
	local k=i
	i=#a
	while i>=k+1 do
		if a[k]<a[i] then break end
		i=i-1
	end
	local l=i
	local z=a[k]
	a[k]=a[l]
	a[l]=z
	reverse(a,k+1,#a+1-(k+1))
	return true
end

n=io.read("*n")
k=io.read("*n")
io.read("*l")
s=io.read("*l")
a={}
for i=1,n do
	a[i]=s:byte(i)
end
table.sort(a)
r=0
repeat
	i=n-k+1
	while i>0 do
		x=i
		y=i+k-1
		while x<y do
			if a[x]~=a[y] then
				break
			end
			x=x+1
			y=y-1
		end
		if x>=y then
			break
		end
		i=i-1
	end
	if i<=0 then
		r=r+1
	end
until not next_permutation(a)
print(r)
```

## Fortran

(こちらは数えるぐらいはAC者がいるようですが)

https://atcoder.jp/contests/abc363/submissions/55861085

```fortran
implicit none
interface
subroutine reverse(a_,start_,size_)
	integer a_(*)
	integer start_,size_
end
logical function next_permutation(a_,n_)
	integer a_(:)
	integer n_
end
end interface
integer n,k,r,i,j,x,y
character(:), allocatable :: s
integer, allocatable :: a(:)
read(*,*) n,k
allocate(character(n+1) :: s)
allocate(a(n))
read(*,*) s
do i=1,n
	a(i)=ichar(s(i:i))
enddo
do i=1,n-1
	do j=i+1,n
		if(a(i).gt.a(j)) then
			r=a(i)
			a(i)=a(j)
			a(j)=r
		endif
	enddo
enddo

r=0
do while(.true.)
	i=n-k+1
	do while(i.gt.0)
	 	x=i
		y=i+k-1
		do while(x.lt.y)
			if(a(x).ne.a(y)) exit
			x=x+1
			y=y-1
		enddo
		if(x.ge.y) exit
		i=i-1
	enddo
	if(i.le.0) r=r+1
	if(.not.next_permutation(a,size(a))) exit
enddo
write(*,"(i0)") r
end

subroutine reverse(a_,start_,size_)
	integer a_(*)
	integer start_,size_
	integer end_,i_
	integer z_
	end_=start_+size_-1
	do i_=0,size_/2-1
		z_=a_(start_+i_)
		a_(start_+i_)=a_(end_-i_)
		a_(end_-i_)=z_
	end do
end

logical function next_permutation(a_,n_)
	integer a_(:)
	integer n_
	integer i_,k_,l_
	integer z_
	next_permutation=.false.
	if((0.le.n_).and.(n_.le.size(a_))) then
		call reverse(a_,n_,size(a_)+1-n_)
		i_=size(a_)-1
		do while(i_.ge.1)
			if(a_(i_).lt.a_(i_+1)) then
				exit
			endif
			i_=i_-1
		enddo
		if(i_.lt.1) then
			call reverse(a_,1,size(a_))
		else
			k_=i_
			i_=size(a_)
			do while(i_.ge.k_+1)
				if(a_(k_).lt.a_(i_)) then
					exit
				endif
				i_=i_-1
			enddo
			l_=i_;
			z_=a_(k_)
			a_(k_)=a_(l_)
			a_(l_)=z_
			call reverse(a_,k_+1,size(a_)+1-(k_+1))
			next_permutation=.true.
		endif
	endif
end
```

## Perl (240725追記)

現時点で私しかACしていません。

![Screenshot from 2024-07-25 10-39-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29692/fab3e125-ec87-8233-26f2-54669a475238.png)

TLEにかなり苦しめられましたが、N==10かつ重複がない場合は3628800を出力して終了することでなんとかACできました。

https://atcoder.jp/contests/abc363/submissions/55939166

```pl
#!/usr/bin/perl
use strict;
use List::Util 'uniqint';

sub permute(&@){
	my $code = shift;
	my @a = sort {$a <=> $b} @_;
	for(;;){
		$code->(@a);
		my $i;
		#push(@a,reverse splice @a, $n);  # partial_permutationに使うものだが、Perlの場合どうやって$nを渡すべきなんだろう…
		for($i=$#a-1;$i>=0;$i--){if($a[$i]<$a[$i+1]){last;}}
		if($i<0){return;}
		my $k=$i;
		for($i=$#a;$i>=$k+1;$i--){if($a[$k]<$a[$i]){last;}}
		my $l=$i;
		@a[$k,$l]=@a[$l,$k];
		push(@a, reverse splice @a, $k+1);
	}
}

<>=~$";
my $n=$`;
my $k=$';
my $s_=<>;
chomp($s_);
my @s=map {ord} split('',$s_);
my $count = uniqint @s;
if($n==10 && $count==10) {
  print 3628800;
  exit;
}

my $r=0;
permute {
	my $i=$n-$k;
	for(;$i>=0;$i--){
		my $x=$i;
		my $y=$i+$k-1;
		for(;$x<$y;$x++,$y--){
			last if($_[$x] != $_[$y]);
		}
		last if($x>=$y);
	}
	$r++ if($i<0);
} @s;
print $r."\n";
```