UVALive 7343 H - Design New Capital

来源:互联网 发布:银湖网骗局 知乎 编辑:程序博客网 时间:2024/05/16 03:07

题目描述:

If you go through history you will come across many fun facts about the capital city of a country.
In many countries the most famous or most populated or most industrialized cities are not declared
capital. For example, Zurich or Geneva is not capital of Switzerland it is Berne. In Australia the capital
is neither Melbourne nor Sydney, it is Canberra and guess what Canberra was built to be capital! In
Brazil Brasilia is capital not Rio.
Head of your country decided to redesign the capital. Dr. Krakow is appointed as the head architect
of this project. Having been in Europe and America, he has vast experience about city life. He wants
to lay roads like New York. That is, if you see from above, it will look like a big 2d grid. He wants
to build the parliament at (0, 0) coordinate of this grid. After that, he asks some people where would
they love to stay. Of course, it is not possible to allow to build homes anywhere the people like. There
are many constraints to consider. One of the constraints is the parliament has to be at the optimal
position. A position is optimal if summation of Manhattan distance to all the houses from the position
is minimum.
For example, suppose there are three proposals to build houses at following positions: (1, 1), (−1, −1)
and (2, 2). If Dr. Krakow approves to build houses at (1, 1) and (−1, −1) then (0, 0) would be optimal
position. But if he approves (1, 1) and (2, 2) then (0, 0) is no more optimal position. Please note, there
may be many optimal positions for some set of approval, but (0, 0) has to be one of them. Given some
proposals, help Dr. Krakow to figure out number of ways he can approve some of the proposals so that
parliament is at one of the optimal positions. Please note, there may be request for the same place
from different persons. In such case Dr. Krakow can approve none or all or some of these proposals.
When computing summation of Manhattan distance, all of the approved proposals are counted, that is,
if there are two approved proposals at the same place, then distance from this place to the parliament
will be counted twice.
Input
The first line of the input will contain a positive integer T (T ≤ 5). Hence T cases follow.
First line of the test case contains number of proposals n (1 ≤ n ≤ 105
). Hence n liness follow, each
describing a proposal x, y (−109 ≤ x, y ≤ 109 and xy ̸= 0).
Output
For each case print case number followed by space separated n numbers where i-th of these numbers
denotes number of ways you can accept i proposals. Since the answer can be very big you need to
present the solution in modulo 7340033.

题解:

1.其实就是中位数.
2.显然奇数不可能,偶数的话是对称4个区域有关系.
3.可以写出公式之后, 发现时卷积,用NTT

重点:

1.中位数,再推,写出公式来优化
2.NTT

代码:

#include <iostream>#include <cstdio>#include <cstring>using namespace std;typedef long long ll;const int M = 7340033;const int maxn = 5e5 + 100;const int key = 100000;int c[5][maxn], num[5];int a1[maxn], a2[maxn];int x1[maxn], x2[maxn];int rev[maxn], n;int add(int a, int b) {    int c = a + b;    if(c >= M)        c -= M;    return c;}int sub(int a, int b) {    if(a < b)        a += M;    return a - b;}int power(int x, int n) {    int res = 1, tmp = x % M;    while(n) {        if(n & 1)            res = (ll)res * (ll)tmp % M;        tmp = (ll)tmp * (ll)tmp % M;        n >>= 1;    }    return res;}int inverse(int x) {    return power(x, M - 2);}void change(int y[], int len) {    int i, j, k;    for(i = 1, j = len / 2; i < len - 1; i++) {        if(i < j) swap(y[i], y[j]);        k = len / 2;        while(j >= k) {            j -= k;            k /= 2;        }        if(j < k) j += k;    }}void fft(int y[], int len, int on) {    change(y, len);    for(int h = 2; h <= len; h <<= 1) {        int unit_p0 = power(3, (M - 1) / h);        if(on == -1)            unit_p0 = inverse(unit_p0);        for(int j = 0; j < len; j += h) {            int unit = 1;            for(int k = j; k < j + h / 2; k++) {                int u = y[k];                int t = (ll)unit * (ll)y[k + h / 2] % M;                y[k] = add(u, t);                y[k + h / 2] = sub(u, t);                unit = (ll)unit * (ll)unit_p0 % M;            }        }    }    if(on == -1) {        int key = inverse(len);        for(int i = 0; i < len; i++) {            y[i] = (ll)y[i] * (ll)key %M;        }    }}void solve() {    for(int i = 0; i < 4; i++) {        int a = num[i];        c[i][0] = 1;        for(int j = 1; j <= key; j++) {            if(j > a)                c[i][j] = 0;            else {                c[i][j] = (ll)c[i][j - 1] * (ll)(a - j + 1) % M * (ll)rev[j] % M;            }        }    }    memset(a1, 0, sizeof(a1));    memset(a2, 0, sizeof(a2));    for(int i = 0; i <= key; i++) {        a1[i] = (ll)c[0][i] * (ll)c[2][i] % M;        a2[i] = (ll)c[1][i] * (ll)c[3][i] % M;    }    int len = key;    int len1 = 1;    while(len1 <2 * len) {        len1 *= 2;    }    fft(a1, len1, 1);    fft(a2, len1, 1);    for(int i = 0; i < len1; i++) {        a1[i] = (ll)a1[i] * (ll)a2[i] % M;    }    fft(a1, len1, -1);    for(int i = 1; i <= n; i++) {        if(i % 2 == 1)            printf("0");        else            printf("%d", a1[i / 2]);        if(i != n) printf(" ");        else printf("\n");    }}int main() {    //freopen("h.txt", "r", stdin);    for(int i = 1; i <= key; i++)        rev[i] = inverse(i);    int ncase;    scanf("%d", &ncase);    for(int _ = 1; _ <= ncase; _++) {        printf("Case %d:\n", _);        scanf("%d", &n);        memset(num, 0, sizeof(num));        for(int i = 1; i <= n; i++) {            int x, y;            scanf("%d%d", &x, &y);            if(x >= 0 && y >= 0)                num[0]++;            if(x <= 0 && y >= 0)                num[1]++;            if(x <=0 && y <= 0)                num[2]++;            if(x >=0 && y <= 0)                num[3]++;        }        solve();    }    return 0;}
0 0
原创粉丝点击