AtCoder-5165 Kleene Inversion

This blog discusses the Kleene Inversion problem from AtCoder, detailing the problem statement, constraints, and providing an analysis of the solution. The author explains how to calculate the inversion number of a concatenated sequence, considering pairs of integers and modulo arithmetic." 137868606,5604553,Python基础实践:函数与算法挑战,"['Python', '开发语言', '算法']

See the original article https://dyingdown.github.io/2019/11/22/AtCoder-5165-Kleene-Inversion/

Kleene Inversion

Problem Statement

We have a sequence of N integers A   =   A 0 ,   A 1 ,   ⋯   ,   A N − 1 A~=~ A_0,~A_1,~ \cdots,~A_{N−1} A = A0, A1, , AN1.

Let B be a sequence of K × N K \times N K×N integers obtained by concatenating K K K copies of A A A. For example, if A   =   1 ,   3 ,   2 A ~=~1,~3,~2 A = 1, 3, 2 and K   =   2 , B   =   1 ,   3 ,   2 ,   1 ,   3 ,   2 K ~=~2, B~=~1,~3,~2,~1,~3,~2 K = 2,B = 1, 3, 2, 1, 3, 2.

Find the inversion number of B, modulo 1 0 9 + 7 10^9+7 109+7.

Here the inversion number of B is defined as the number of ordered pairs of integers ( i ,   j )   ( 0 ≤ i < j ≤ K × N − 1 ) (i,~j)~(0≤i<j≤K \times N−1) (i, j) (0i<jK×N1) such that B i > B j B_i>B_j Bi>Bj.

Constraints

  • All values in input are integers.
  • 1≤ N N N ≤2000
  • 1≤ K K K ≤109
  • 1≤ A i A_i Ai ≤2000

Input

Input is given from Standard Input in the following format:

N K
A0 A1 … AN−1

Output

Print the inversion number of B, modulo 109+7.

Sample Input 1

2 2
2 1

Sample Output 1

3

In this case, B=2,1,2,1. We have:

  • B 0 > B 1 B_0>B_1 B0>B1
  • B 0 > B 3 B_0>B_3 B0>B3
  • B 2 > B 3 B_2>B_3 B2>B3

Thus, the inversion number of B B B is 3.

Sample Input 2

3 5
1 1 1

Sample Output 2

0

A may contain multiple occurrences of the same number.

Sample Input 3

10 998244353
10 9 8 7 5 6 3 4 2 1

Sample Output 3

185297239

Be sure to print the output modulo 1 0 9 + 7 10^9+7 109+7.

Analysis

The answer of the problem has a regular pattern.

For example, there is a sequence A and for number A n A_n An in A, the number that is bigger than A n A_n An has two parts: the part before A n A_n An and the part after A n A_n An. We copy A for K times.

Firstly, we deal with the back part. If the first A has B numbers bigger than A n A_n An and after A n A_n An, it’s the same to the rest K-1 sequences. So for the first A n A_n An, it has B × K B \times K B×K pairs. And the second A, it has B × ( K − 1 ) B \times (K - 1) B×(K1) numbers. ⋯ \cdots . Until the last A n A_n An, it has B pairs. So the total answer for the pairs after A n A_n An is B × ( K + ( K − 1 ) + ⋯ + 1 ) = B × K × ( K + 1 ) 2 B \times (K + (K - 1) + \cdots + 1) = B \times \frac{K \times (K + 1)}{2} B×(K+(K1)++1)=B×2K×(K+1)

Secondly, we deal with the front part. It’s the same to the back part. So I’ll just give an formula here. The answer for the pairs before A n A_n An is F × ( ( K − 1 ) + ( K − 2 ) + ⋯ + 1 ) = F × K × ( K − 1 ) 2 F \times ((K - 1) + (K - 2) +\dots+1) = F \times \frac{K \times (K - 1)}{2} F×((K1)+(K2)++1)=F×2K×(K1) . F is the number of numbers that bigger than A n A_n An and before A n A_n An.

This is only for one A n A_n An. You need to traverse A to find all answers. Add the front part and the back part together and don’t forget to modulo 1 0 9 + 7 10^9+7 109+7.

Code

#include <iostream>

const long long mod = 1e9 + 7;
using namespace std;
long long a[10000];

int main() {
    long long n, k;
    cin >> n >> k;
    for (long long i = 0; i < n; i++) {
        cin >> a[i];
    }
    long long sum = 0;
    for (long long i = 0; i < n; ++i) {
        long long before_i = 0, after_i = 0;
        for (long long j = 0; j < n; ++j) {
            if (i == j) continue;
            else {
                if (a[i] > a[j]) {
                    if (j < i) before_i++;
                    else after_i++;
                }
            }
        }
        sum += (after_i % mod) * (k * (k + 1)  / 2 % mod) % mod;
        sum += (before_i % mod) * (k * (k - 1) / 2 % mod) % mod;
    }
    cout << sum % mod << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值