PKU 3761 - Bubble Sort

問題概要

n, kが入力される。
n個の要素がある数列をバブルソートでソートされることを考える。
このとき、数列が並び終わるまでに、バブルソートの一重ループ目を実行した回数がkであるとする。
このようになる数列の初期配置は、何パターンあるか求めよ。

解法

ごめんなさい。
法則性ありそうだったけど、自力で導きだせなかったので、OEIS突っ込みました。
http://oeis.org/A056151

階上は、先に計算しておく。
累乗は、繰り返し二乗法で。
入力は、scanfで。

プログラム

/*
0回でソートできるのならば、各数字はソートされた状態でなければならない。
1 2 3 4

1回でソートできるのならば、各数字は「本来あるべき位置の1つ右」以下に位置すればおk。
さらに、最低でも1つの数字が本来あるべき位置でない位置になければならない。

2 1 3 4 <- 1は、本来あるべき位置より1つ右に位置するのでOK
4 1 2 3 <- 4は、本来あるべき位置より左側に位置するのでOK
2 3 1 4 <- 1は、本来あるべき位置より2つ右に位置しているのでNG
1 2 3 4 <- ソートされちゃってるのでNG

2回でソートできるのであれば、各数字は「本来あるべき位置の2つ右」以下に位置すればOK。
さらに、最低1つの要素は、本来あるべき位置より2つ右の位置になければならない。

2 3 1 <- 1は、本来あるべき位置より2つ右にあるからOK
3 2 1 <- 1は、本来あるべき位置より2つ右にあるからOK
1 2 3 <- sortされちゃってるからNG
3 1 2 <- 条件満たしてないのでNG
 */
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;

typedef long long ll;

#define MOD 20100713LL

ll fact[1000002];

ll modPow(ll x, ll n){
  if(n == 0) return 1LL;
  ll res = modPow(x * x % MOD, n / 2LL);
  if(n & 1LL) res = res * x % MOD;
  return res;
}

int main(){
  fact[0] = fact[1] = 1;
  for(ll i = 2; i <= 1000000; i++){
    fact[i] = fact[i - 1] * i;
    fact[i] %= MOD;
  }

  int T;
  ll n, k;

  scanf("%d", &T);

  while(T--){
    scanf("%lld%lld", &n, &k);

    ll cal = fact[k] * modPow(k + 1, n - k) % MOD;
    cal -= (fact[k - 1] * modPow(k, n - k + 1)) % MOD;
    cal = (cal + MOD) % MOD;

    printf("%lld\n", cal);
  }
}