思路:这题用到了组合数学中类似构造逆序数的思路。 对于每个排列a1,a2,-----,an,唯一对应一个反序列表b1,b2,------,bn;bj为位于aj的左边但大于aj的元素个数。
例如,对于5,9,1,8,2,6,4,7,3,有反序表:0,0,2,1,3,2,2,4,2,6.
令
g(k)
表示最大逆序对小于等于
k
的数列个数。
那么
g(k)=k!∗(k+1)n−k
//比如只有5个数,那5这个位置只能取反序数0,4只能取0或1;
所求的答案为
g(k)−g(k−1)
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
const int maxn = 1000008;
using namespace std;
__int64 inv[maxn], mod = 20100713;
void involutionmod() {
inv[1] = 1; inv[2] = 2;
for(int i = 3; i < 1000000; i++) {
inv[i] = i*inv[i-1]%mod;
}
}
__int64 multimod(__int64 a, __int64 n, __int64 m) {
__int64 tmp = a, res = 1LL;
while(n) {
if (n&1LL) {
res *= tmp;
res %= m;
}
tmp *= tmp;
tmp %= m;
n >>= 1LL;
}
return res;
}
int main() {
int t, n, k;
__int64 result;
involutionmod();
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &k);
if (!k){
printf("1\n");
continue;
}
result = inv[k]*(multimod(k + 1, n - k, mod) + mod - multimod(k, n- k, mod))%mod;
printf("%I64d\n", result);
}
return 0;
}