您的位置:首页 > 其它

UVALive 7343 H - Design New Capital

2016-01-19 10:31 344 查看

题目描述:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: