The 2014 ACM-ICPC Asia Regional Anshan Online
【A】无向图的双联通子图计数、DP+状态压缩
【C】DP+状态压缩
【D】离散数学+DP (感觉可出)
【F】LCT模板题(-_-///LCT是啥!!!!)
【H】染色+搜索
【I】阅读理解+记忆化搜索
【J】物理题,数论,高斯消元法(感觉可出)
Rotate
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Special Judge
Your little sister likes to rotate things. To put it easier to analyze, your sister makes n rotations. In the i-th time, she makes everything in the plane rotate counter-clockwisely around a point ai by a radian of pi.
Now she promises that the total effect of her rotations is a single rotation around a point A by radian P (this means the sum of pi is not a multiplier of 2π).
Of course, you should be able to figure out what is A and P :).
For each test case, the first line contains an integer n denoting the number of the rotations. Then n lines follows, each containing 3 real numbers x, y and p, which means rotating around point (x, y) counter-clockwisely by a radian of p.
We promise that the sum of all p's is differed at least 0.1 from the nearest multiplier of 2π.
T<=100. 1<=n<=10. 0<=x, y<=100. 0<=p<=2π.
Your answer will be considered correct if and only if for x, y and p, the absolute error is no larger than 1e-5.
1 3 0 0 1 1 1 1 2 2 1
【Sample Output】
1.8088715944 0.1911284056 3.0000000000
【题意】
1 /* *********************************************** 2 MYID : Chen Fan 3 LANG : G++ 4 PROG : B1002 5 ************************************************ */ 6 7 #include <iostream> 8 #include <cstdio> 9 #include <cmath> 10 11 #define Pi 3.141592657 12 13 typedef struct poi 14 { 15 double x,y; 16 } point; 17 18 using namespace std; 19 20 point rotate(point v,point p,double angle) 21 { 22 point ret=p; 23 v.x-=p.x,v.y-=p.y; 24 p.x=cos(angle); 25 p.y=sin(angle); 26 ret.x+=v.x*p.x-v.y*p.y; 27 ret.y+=v.x*p.y+v.y*p.x; 28 return ret; 29 } 30 31 int main() 32 { 33 int t; 34 scanf("%d",&t); 35 for (int tt=1;tt<=t;tt++) 36 { 37 int n; 38 scanf("%d",&n); 39 point p1={20.123,6.678},p2={3.414,10.123}; 40 point p0={(p1.x+p2.x)/2,(p1.y+p2.y)/2}; 41 for (int i=1;i<=n;i++) 42 { 43 point now; 44 double p; 45 scanf("%lf%lf%lf",&now.x,&now.y,&p); 46 p1=rotate(p1,now,p); 47 p2=rotate(p2,now,p); 48 } 49 50 point p10; 51 p10.x=(p1.x+20.123)/2; 52 p10.y=(p1.y+6.678)/2; 53 double k1=(p1.y-p10.y)/(p1.x-p10.x); 54 k1=-1/k1; 55 double b1=p10.y-k1*p10.x; 56 57 point p20; 58 p20.x=(p2.x+3.414)/2; 59 p20.y=(p2.y+10.123)/2; 60 double k2=(p2.y-p20.y)/(p2.x-p20.x); 61 k2=-1/k2; 62 double b2=p20.y-k2*p20.x; 63 64 double xx=(b2-b1)/(k1-k2); 65 double yy=k1*xx+b1; 66 67 double bb=(xx-3.414)*(xx-3.414)+(yy-10.123)*(yy-10.123); 68 double cc=(xx-p2.x)*(xx-p2.x)+(yy-p2.y)*(yy-p2.y); 69 double aa=(p2.x-3.414)*(p2.x-3.414)+(p2.y-10.123)*(p2.y-10.123); 70 double ct=(bb+cc-aa)/(2*sqrt(bb)*sqrt(cc)); 71 72 point p3={2*xx-p0.x,2*yy-p0.y}; 73 point p4={(p1.x+p2.x)/2,(p1.y+p2.y)/2}; 74 75 double k3=(p3.y-p0.y)/(p3.x-p0.x); 76 double b3=p3.y-k3*p3.x; 77 78 point pp={xx,yy}; 79 point p5=rotate(p0,pp,1); 80 81 if ((p4.x*k3+b3-p4.y)*(p5.x*k3+b3-p5.y)>0) printf("%.10lf %.10lf %.10lf\n",xx,yy,acos(ct)); 82 else printf("%.10lf %.10lf %.10lf\n",xx,yy,2*Pi-acos(ct)); 83 } 84 85 return 0; 86 }
【启发】
对于计算几何的东西,真的需要提前准备下模板,主要的几何思想要看数学能力。
Walk
Time Limit: 30000/15000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
The nation looks like a connected bidirectional graph, and I am randomly walking on it. It means when I am at node i, I will travel to an adjacent node with the same probability in the next step. I will pick up the start node randomly (each node in the graph has the same probability.), and travel for d steps, noting that I may go through some nodes multiple times.
If I miss some sights at a node, it will make me unhappy. So I wonder for each node, what is the probability that my path doesn't contain it.
For each test case, the first line contains 3 integers n, m and d, denoting the number of vertices, the number of edges and the number of steps respectively. Then m lines follows, each containing two integers a and b, denoting there is an edge between node a and node b.
T<=20, n<=50, n-1<=m<=n*(n-1)/2, 1<=d<=10000. There is no self-loops or multiple edges in the graph, and the graph is connected. The nodes are indexed from 1.
Your answer will be accepted if its absolute error doesn't exceed 1e-5.
2 5 10 100 1 2 2 3 3 4 4 5 1 5 2 4 3 5 2 5 1 4 1 3 10 10 10 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 4 9
【Sample Output】
0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.6993317967 0.5864284952 0.4440860821 0.2275896991 0.4294074591 0.4851048742 0.4896018842 0.4525044250 0.3406567483 0.6421630037
【题意】
随机随机随机!!...在一张无向图中,随机选定一个起点出发,之后的每一步都是等概率的。有一些点不能被到达,这里要求的就是每一个点不能被到达的概率。
【分析】
概率DP的题目做得太少了,以至于当时最后的时间基本都花在这里了,还是没有什么想法。每次都是这样,比完之后才能想到最后的正解,唉。当时纠结的是怎么记录访问过的路径,然后判断每一次遍历完之后有哪些点是该次没有被访问过的。这个想法完全是不可行的。
既然是判断一个点不能到达的概率,则直接把这个点从图中去掉,依次递推其他所有点在走完d步之后到达的概率,结果的总和就是不能到达该点的概率。
概率DP的状态转移方程:f(i,j)=f(i-1,front[j])/num[front[j]]
求解的时候,依次枚举一个点,把这个点拿掉,然后递推DP结果,由于当前步的状态只与前一步有关,这里可以用滚动数组处理。
前向星是我的个人习惯,这里恰好需要一个计算的变量,前向星的结构恰好满足。
1 /* *********************************************** 2 MYID : Chen Fan 3 LANG : G++ 4 PROG : E1005 5 ************************************************ */ 6 7 #include <iostream> 8 #include <cstdio> 9 #include <algorithm> 10 #include <cstring> 11 12 using namespace std; 13 14 typedef struct nod 15 { 16 int a,b; 17 } node; 18 node a[3000]; 19 int start[60],num[60],n,m,d,tot; 20 bool ma[60][60]; 21 double ans[60],temp[2][60]; 22 23 bool op(node a,node b) 24 { 25 if (a.a==b.a) return a.b<b.b; 26 else return a.a<b.a; 27 } 28 29 int main() 30 { 31 freopen("E1005.txt","r",stdin); 32 33 int t; 34 scanf("%d",&t); 35 for (int tt=1;tt<=t;tt++) 36 { 37 scanf("%d%d%d",&n,&m,&d); 38 memset(ma,0,sizeof(ma)); 39 int tail=0; 40 for (int i=1;i<=m;i++) 41 { 42 int x,y; 43 scanf("%d%d",&x,&y); 44 if (!ma[x][y]) 45 { 46 ma[x][y]=true; 47 ma[y][x]=true; 48 tail++; 49 a[tail].a=x; 50 a[tail].b=y; 51 tail++; 52 a[tail].a=y; 53 a[tail].b=x; 54 } 55 } 56 sort(&a[1],&a[tail+1],op); 57 int o=0; 58 memset(num,0,sizeof(num)); 59 for (int i=1;i<=tail;i++) 60 { 61 if (o!=a[i].a) 62 { 63 o=a[i].a; 64 start[o]=i; 65 } 66 num[o]++; 67 } 68 69 memset(ans,0,sizeof(ans)); 70 for (int k=1;k<=n;k++) 71 { 72 memset(temp,0,sizeof(temp)); 73 int key=1; 74 for (int i=1;i<=n;i++) 75 if (i!=k) temp[0][i]=1.0/n; 76 77 for (int i=1;i<=d;i++) 78 { 79 memset(temp[key],0,sizeof(temp[key])); 80 for (int j=1;j<=n;j++) 81 { 82 for (int o=0;o<num[j];o++) 83 if (a[start[j]+o].b!=k) 84 temp[key][a[start[j]+o].b]+=temp[1-key][j]/(double)num[j]; 85 } 86 key=1-key; 87 } 88 key=1-key; 89 90 for(int i=1;i<=n;i++) 91 if (i!=k) ans[k]+=temp[key][i]; 92 } 93 94 for (int i=1;i<=n;i++) 95 printf("%.10lf\n",ans[i]); 96 } 97 98 return 0; 99 }
【启发】
题目中碰到一个点对前后状态影响较大,无法直接推算或者直接算需要涉及到大量复杂记录的情况,可以考虑先把这个点拿掉,完成之后再放上去,或者先把其变为普通点,完成后再恢复(后面有广州赛区的D题就是这种思想)
Osu!
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Special Judge
Now you are given the task to write a calculator for this system.
For each test case, the first line contains an integer n, denoting the number of songs you have played. The second line contains n integers a1, a2, ..., an separated by a single space, denoting the score of each song.
T<=20, n<=50, 1<=ai<=500.
Your answers will be considered correct if its absolute error is smaller than 1e-5.
1 2 530 478
【Sample Output】
984.1000000000