Robots
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 60 Accepted Submission(s): 13
Problem Description
QXJ has N robots on the plane, the i-th is at (xi,yi), numbereded 1 to N. Every robot is painted by one kind of color, numbered 1 to M.
Each robots can move K times. In one move,a robot at (x,y) can move to (x−1,y),(x,y+1),(x+1,y),(x,y−1).
After exactly K moves, she wants robots with same color to gather at the same postion and the robot on the i-th color gather at different postion with robots on (i-1)-th or (i+1)-th color.
Now she wants to know how many ways of moving these robots following to rules above.
Two ways are different if one of final postions of certain robot is different or there is at least one robot whose moving path is different.
Input
The first line is the number of test cases T(T≤10).
The first line of each case contains three integer N(1≤N≤200),M(1≤M≤20),K(1≤K≤500), indicating the number of robots ,the number of color and the number of steps robots can move.
The second line,contains M integer mi, indicating the number of robots with the i-th color.
The robots numbered [1,m1] are on the 1st color.The robots numbered [m1+1,m1+m2] are one the 2nd color, ans so on.
The next N line,each contains two integers xi,yi, indicating the postion of i-th robots..
(0≤|xi,yi|≤250).
Output
For each test case, output a single line "Case #x: y", where x is the case number, starting from 1. And y is the answer(module 109+7).
Sample Input
2
3 3 1
1 1 1
1 0
0 1
1 2
4 2 2
2 2
0 1
0 3
0 2
0 4
Sample Output
Case #1: 49
Case #2: 256
Author
UESTC
Source
题意: 有n个机器人,共有m种颜色,分别分布在一个二维坐标平面上,每次移动可以向四联通的地方移动,多个机器人可以重合。 问所有机器人分别恰好走K步后,每种颜色的机器人聚集在一起,并且相邻两种颜色不聚集在一起的方案数。
题解: 一定不要读错题,这题只要求编号相邻的颜色的机器人不能聚集在一个点,于是难度锐减。 可以首先令坐标变化,x‘=x+y,y‘=x-y。 如此,当(x,y)向四联通方格发生变化时,及变化量为(+-1,0)(0,+-1)时,(x‘,y‘)的变化为(+-1,+-1)。 无论原坐标如何改变,新坐标的两维都会发生改变。 在考虑到每个新坐标唯一确定了原坐标,这就给我们一个很好的性质: 新坐标两维可以分开考虑x‘、y‘无论如何分开分别变化K次,我们都可以在原坐标上解释这种变化,并且移动步数也为K。 可以如此,先令Gx[i][S]为第i种颜色的机器人的X坐标聚集在S的方案数,Gy[i][S]同理。 然后在令f[i]为前i种颜色的机器人合法的聚集的方案数,那么利用容斥就可以计算这个东西。
1 const int N = 210, M = 25, K = 510, SIZE = 3010, MOD = 1e9 + 7; 2 struct Point { 3 int x, y; 4 5 inline void read() { 6 scanf("%d%d", &x, &y); 7 } 8 9 inline void fix() { 10 int tx = x, ty = y; 11 x = tx + ty, y = tx - ty; 12 } 13 14 inline int getCoor(int xy) const { 15 return xy ? y : x; 16 } 17 } arr[N]; 18 int n, m, k, f[N]; 19 int gather[2][M][SIZE]; 20 // coordinate -1500 ~ 1500 21 // real coordinate should be : i - 1501 22 // Size is SIZE 23 // 0 -> xcoordinate 1 -> y-coordinate 24 int dp[N], allAt[2][SIZE]; 25 26 inline int add(int x, int y) { 27 return (x + 0ll + MOD + 0ll + y) % MOD; 28 } 29 30 inline int mul(int x, int y) { 31 return ((x * 1ll * y) % MOD + MOD) % MOD; 32 } 33 34 int C[K][K]; 35 inline void init() { 36 for(int i = 0; i < K; ++i) C[i][0] = 1; 37 for(int i = 1; i < K; ++i) 38 for(int j = 1; j <= i; ++j) 39 C[i][j] = add(C[i - 1][j - 1], C[i - 1][j]); 40 } 41 42 inline int move(int st, int ed) { 43 int delta = abs(ed - st); 44 int freeMove = k - delta; 45 if(freeMove < 0 || (freeMove & 1)) return 0; 46 return C[k][freeMove / 2]; 47 } 48 49 inline void solve() { 50 for(int i = 1; i < m; ++i) f[i] += f[i - 1]; 51 for(int i = 0; i < n; ++i) arr[i].fix(); 52 53 for(int xy = 0; xy < 2; ++xy) 54 for(int i = 0; i < m; ++i) 55 for(int w = 0; w < SIZE; ++w) { 56 gather[xy][i][w] = 1; 57 for(int j = i ? f[i - 1] : 0; j < f[i]; ++j) 58 gather[xy][i][w] = mul(gather[xy][i][w], 59 move(w - 1501, arr[j].getCoor(xy))); 60 } 61 62 for(int i = 0; i < m; ++i) { 63 dp[i] = 0; 64 65 for(int xy = 0; xy < 2; ++xy) 66 for(int w = 0; w < SIZE; ++w) allAt[xy][w] = 1; 67 for(int j = i, coe = 1; j >= 0; --j, coe *= -1) { 68 int allGather[2] = {0, 0}; 69 for(int xy = 0; xy < 2; ++xy) 70 for(int w = 0; w < SIZE; ++w) { 71 allAt[xy][w] = mul(allAt[xy][w], gather[xy][j][w]); 72 allGather[xy] = add(allGather[xy], allAt[xy][w]); 73 } 74 75 int combine = mul(allGather[0], allGather[1]); 76 dp[i] = add(dp[i], mul(mul(coe, j ? dp[j - 1] : 1), combine)); 77 } 78 } 79 80 printf("%d\n", dp[m - 1]); 81 } 82 83 int main() { 84 freopen("f.in", "r", stdin); 85 init(); 86 int testCase; 87 scanf("%d", &testCase); 88 for(int testIndex = 1; testIndex <= testCase; ++testIndex) { 89 printf("Case #%d: ", testIndex); 90 scanf("%d%d%d", &n, &m, &k); 91 for(int i = 0; i < m; ++i) scanf("%d", &f[i]); 92 for(int i = 0; i < n; ++i) arr[i].read(); 93 solve(); 94 } 95 return 0; 96 }