[关闭]
@zzzc18 2017-07-16T13:38:40.000000Z 字数 3824 阅读 640

Regular Contest 076

AtCoder


Problem_C

Problem Statement

Snuke has N dogs and M monkeys. He wants them to line up in a row.

As a Japanese saying goes, these dogs and monkeys are on bad terms. ("ken'en no naka", literally "the relationship of dogs and monkeys", means a relationship of mutual hatred.) Snuke is trying to reconsile them, by arranging the animals so that there are neither two adjacent dogs nor two adjacent monkeys.

How many such arrangements there are? Find the count modulo 109+7 (since animals cannot understand numbers larger than that). Here, dogs and monkeys are both distinguishable. Also, two arrangements that result from reversing each other are distinguished.

Constraints

Sample Input 1

2 2

Sample Output 1

8

Sample Input 2

1 8

Sample Output 2

0

Sample Input 3

3 2

Sample Output 3

12

Sample Input 4

100000 100000

Sample Output 4

530123477


Solution

对于n和m相差大于等于二的,不考虑,直接输出0

当n和m相等时,有种情况(y因为奇数位放猴与偶数位放猴时两种等值但不同的情况)

当n和m相差1时,只能狗和猴插空站,整体上就一种形态,如例3,只能NMNMN这样站,共种情况

注意计算过程中取模,要开long long


  1. #include<cstdio>
  2. #include<cmath>
  3. #include<algorithm>
  4. #define LL long long
  5. #define MOD 1000000007
  6. using namespace std;
  7. LL n,m,ans;
  8. LL cal(LL x){
  9. LL i;LL re=1;
  10. for(i=1;i<=x;i++){
  11. re=(re*i)%MOD;
  12. }
  13. return re;
  14. }
  15. int main(){
  16. scanf("%lld%lld",&n,&m);
  17. if(abs(m-n)>=2){
  18. printf("0\n");
  19. return 0;
  20. }
  21. if(m==n){
  22. LL t=cal(n);
  23. ans=(t*t*2)%MOD;
  24. }
  25. else{
  26. ans=(cal(m)*cal(n))%MOD;
  27. }
  28. printf("%lld\n",ans);
  29. return 0;
  30. }

Problem_D

Problem Statement

There are N towns on a plane. The i-th town is located at the coordinates (xi,yi). There may be more than one town at the same coordinates.

You can build a road between two towns at coordinates (a,b) and (c,d) for a cost of min(|a−c|,|b−d|) yen (the currency of Japan). It is not possible to build other types of roads.

Your objective is to build roads so that it will be possible to travel between every pair of towns by traversing roads. At least how much money is necessary to achieve this?

Constraints



All input values are integers

Sample Output 1

3
1 5
3 9
7 8

Sample Input 1

3

Sample Input 2

6
8 3
4 9
12 19
18 1
13 5
7 6

Sample Output 2

8


Solution

由于边权只与x的差值和y的差值有关,可以分别考虑走x和走y

如果按x值排序,显然若前三个点为A,B,C,我们一定会连A->B->C而不是A->C->B或其他排列,所以我们只连的边,边权为
再按y来排序,方法同上;
总共只连了条边然后Kruskal求解


我感觉还是官方讲得好

We are asked to compute the minimum spanning tree. Between two points (a,b) and (c,d), instead of adding an edge of cost min(|a−c|,|b−d|), we add two edges: one edge with cost |a−c| and one edge with cost |b−d|. Suppose that there are three points p,q,r, and their x-coordinates satisfy xp < xq < xr. Then, the edge between p and r with cost xr−xp never appear in the MST (it is better to use an edge between p and q with cost xq −xp and an edge between q and r with cost xr −xq). Thus, we only need to consider the following 2(N −1) edges: 
• We sort the point by their x-coordinates, and for each adjacent pair of points add an edge between them (the cost is the difference of their x-coordinates). 
• We sort the point by their y-coordinates, and for each adjacent pair of points add an edge between them (the cost is the difference of their y-coordinates).
We compute the MST of these edges. This can be done in O(NlogN).

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cmath>
  4. #define MAXN 100009
  5. using namespace std;
  6. int n;
  7. struct data{
  8. int x,y,id;
  9. }a[MAXN];
  10. struct E{
  11. int from,to,val,next;
  12. }edge[MAXN<<1];
  13. int head[MAXN],edge_num;
  14. int ans;
  15. int fa[MAXN];
  16. bool cmp1(const data &q,const data &w){
  17. return q.x<w.x;
  18. }
  19. bool cmp2(const data &q,const data &w){
  20. return q.y<w.y;
  21. }
  22. bool cmp3(const E &q,const E &w){
  23. return q.val<w.val;
  24. }
  25. int Find(int x){
  26. if(fa[x]!=x) fa[x]=Find(fa[x]);
  27. return fa[x];
  28. }
  29. void addedge(int x,int y,int v){
  30. edge[++edge_num].next=head[x];
  31. edge[edge_num].to=y;
  32. edge[edge_num].from=x;
  33. edge[edge_num].val=v;
  34. head[x]=edge_num;
  35. }
  36. void Kruskal(){
  37. sort(edge+1,edge+edge_num+1,cmp3);
  38. int i;int cnt=0;
  39. for(i=1;i<=n;i++)
  40. fa[i]=i;
  41. for(i=1;i<=edge_num;i++){
  42. int ff=Find(edge[i].from),tt=Find(edge[i].to);
  43. if(ff!=tt){
  44. fa[ff]=tt;
  45. ans+=edge[i].val;
  46. cnt++;
  47. if(cnt==n-1)
  48. return;
  49. }
  50. }
  51. }
  52. void solve(){
  53. int i;
  54. sort(a+1,a+n+1,cmp1);
  55. for(i=2;i<=n;i++)
  56. addedge(a[i-1].id,a[i].id,a[i].x-a[i-1].x);
  57. sort(a+1,a+n+1,cmp2);
  58. for(i=2;i<=n;i++)
  59. addedge(a[i-1].id,a[i].id,a[i].y-a[i-1].y);
  60. Kruskal();
  61. printf("%d\n",ans);
  62. }
  63. int main(){
  64. scanf("%d",&n);
  65. int i;
  66. for(i=1;i<=n;i++)
  67. scanf("%d%d",&a[i].x,&a[i].y),a[i].id=i;
  68. solve();
  69. return 0;
  70. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注