CPC23 2014-1 B.Crossings(求逆序数)

来源:互联网 发布:淘宝联盟 高佣活动 编辑:程序博客网 时间:2024/05/21 14:07

题目链接:http://acm.hrbust.edu.cn/
B.CrossingsTime Limit: 3000 MSMemory Limit: 32768 KTotal Submit: 349(65 users)Total Accepted: 38(38 users)Special Judge: NoDescription

Given a permutation P of {0, 1, ..., n − 1}, we define the crossing number of it as follows. Write the sequence 0, 1, 2, . . . , n − 1 from left to right above the sequence P(0), P(1), . . . , P(n − 1). Draw a straignt line from 0 in the top line to 0 in the bottom line, from 1 to 1, and so on. The crossing number of P is the number of pairs of lines that cross. For example, if n = 5 and P = [1, 3, 0, 2, 4], then the crossing number of P is 3, as shown in the figure below:  


In this problem a permutation will be specified by a tuple (n, a, b), where n is a prime and a and b are integers (1<=a<=n-1 and 0<=b<=n-1). We call this permutation Perm(n, a, b), and the ith element of it is (a*i+b) mod n (with i in the range [0, n − 1]). So the example above is specified by Perm(5, 2, 1).


Input

There are several test cases in the input file. Each test case is specified by three space-separated numbers n, a, and b on a line. The prime n will be at most 1,000,000. The input is terminated with a line containing three zeros.

Output

For each case in the input print out the case number followed by the crossing number of the permutation.Follow the format in the example output.

Sample Input

5 2 1

19 12 7

0 0 0

Sample Output

Case 1: 3

Case 2: 77

题目大意:通过如题所述变换,如图,求交叉点个数。

由于通过变换位置得到的交叉,提到前面的数字自然会与放在后面的数字形成交叉,也就是求逆序数即可。

采用归并排序nlog(n)的求逆序数方式可过。

AC代码(2443ms):

#include <cstdio>#define MAXN 1000010using namespace std;typedef long long LL;LL n, x, y;LL a[MAXN], tmp[MAXN];long long result;void merge(int l, int mid, int r) {    int i, j, k;    i = l, j= mid + 1, k = 1;    while(i<= mid && j <= r) {        if(a[j] < a[i]) {            tmp[k++] = a[j++];            result += mid - i + 1;        } else            tmp[k++] = a[i++];    }    while(i <= mid)  tmp[k++] = a[i++];    while(j <= r) tmp[k++] = a[j++];    for(i = l, k = 1; i<= r; i++, k++)        a[i] = tmp[k];}void merge_sort(int l, int r) {    if(l < r) {        int mid = (l + r) / 2;        merge_sort(l, mid);        merge_sort(mid + 1, r);        merge(l, mid, r);    }}int main() {    int cnt = 0;    while(~scanf("%lld%lld%lld", &n, &x, &y)) {        if(n == 0) break;        for(int i = 1; i <= n; i++) {            a[i] = (x * (LL)(i - 1) + y) % n;        }        result = 0LL;        merge_sort(1, n);        printf("Case %d: %lld\n", ++cnt, result);      }    return 0;}

PS:此题可能是卡了下线段树的常数2nlog(n),导致T了= =|||


0 0
原创粉丝点击