刚到省实验的第一次考试,大家水平都相差不多,也基本没有分出什么名次。
这回考试的题目第一个有一点水,是USACO 2.2.4,也算是技巧性的题目了,具体的不再多说,可以看nocow上的解析。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /** 2 *Prob : partya 3 *Data : 2012-6-12 4 *Sol : 容斥+搜索 5 */ 6 7 #include <algorithm> 8 #include <string> 9 #include <iostream> 10 #include <cstdio> 11 #include <cstring> 12 13 #define MaxANS 10000000 14 15 using namespace std; 16 17 string ans[MaxANS]; 18 int n,c,num=0; 19 int way[10]; 20 int now[10]; 21 int final[10]; 22 23 void turn(int x) 24 { 25 if (x==1) 26 for (int i=1; i<=6; i++) 27 now[i]=(now[i]+1)%2; 28 if (x==2) 29 for (int i=1; i<=6; i+=2) 30 now[i]=(now[i]+1)%2; 31 if (x==3) 32 for (int i=2; i<=6; i+=2) 33 now[i]=(now[i]+1)%2; 34 if (x==4) { 35 now[1]=(now[1]+1)%2; 36 now[4]=(now[4]+1)%2; 37 } 38 } 39 40 void doit() 41 { 42 for (int i=1; i<=6; i++) 43 now[i]=1; 44 for (int i=1; i<=c; i++) 45 turn(way[i]); 46 } 47 48 bool check() 49 { 50 for (int i=1; i<=6; i++) 51 { 52 if (final[i]==2) continue; 53 if (final[i]!=now[i]) return false; 54 } 55 return true; 56 } 57 58 void copy_str() 59 { 60 string s; 61 for (int i=1; i<=n; i++) 62 { 63 int tmp=i%6; 64 if (tmp==0) tmp=6; 65 s+=now[tmp]+'0'; 66 } 67 for (int i=1; i<=num; i++) 68 if (s==ans[i]) return; 69 ans[++num]=s; 70 } 71 72 void work(int c) 73 { 74 if (c==0) { 75 doit(); 76 if ( check() ) 77 copy_str(); 78 return; 79 } 80 81 for (int i=1; i<=4; i++) 82 { 83 way[c]=i; 84 c--; 85 work(c); 86 c++; 87 } 88 } 89 90 int main() 91 { 92 freopen("partya.in","r",stdin); 93 freopen("partya.out","w",stdout); 94 95 scanf("%d%d",&n,&c); 96 97 while (c>4) c-=2; 98 99 int tmp; 100 for (int i=1; i<=10; i++) 101 final[i]=2; 102 scanf("%d",&tmp); 103 while (tmp!=-1) 104 { 105 tmp%=6; 106 if (tmp==0) tmp=6; 107 final[tmp]=1; 108 scanf("%d",&tmp); 109 } 110 scanf("%d",&tmp); 111 while (tmp!=-1) 112 { 113 tmp%=6; 114 if (tmp==0) tmp=6; 115 final[tmp]=0; 116 scanf("%d",&tmp); 117 } 118 119 work(c); 120 121 sort(ans+1,ans+1+num); 122 123 for (int i=1; i<=num; i++) 124 { 125 cout<<ans[i]; 126 cout<<endl; 127 } 128 129 fclose(stdin); fclose(stdout); 130 return 0; 131 }
第二道题目是求树上的最长距离,可以先搜索一遍再用LCA求解,代码量有一点儿大,就没有去写,回来补上。
第三道题比较有意思,是博弈论中的Nim取数游戏,需要注意的就是每次最多取L个石子,那么可以通过SG函数来把他转化为一个很常见的取数游戏模型。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 /** 2 *Prob : rocks 3 *Data : 2012-6-12 4 *Sol : Nim游戏+SG函数 5 */ 6 7 #include <algorithm> 8 #include <string> 9 #include <iostream> 10 #include <cstdio> 11 #include <cstring> 12 13 #define MaxN 100100 14 15 using namespace std; 16 17 struct edge 18 { 19 int y,next; 20 } e[MaxN]; 21 int n,t,l,ans,now,T,x,tot=0; 22 int first[MaxN],h[MaxN],num[MaxN],a[MaxN]; 23 24 void add(int x,int y) 25 { 26 e[++tot].next=first[x]; 27 e[tot].y=y; 28 first[x]=tot; 29 } 30 31 void init() 32 { 33 memset(h,0,sizeof(h)); 34 int open=1,closd=0; 35 h[1]=1; num[1]=1; 36 int tmn,tme; 37 while (closd<open) 38 { 39 tmn=h[++closd]; 40 tme=first[tmn]; 41 while (tme!=0) 42 { 43 int tmy=e[tme].y; 44 h[++open]=tmy; 45 num[tmy]=num[tmn]+1; 46 tme=e[tme].next; 47 } 48 } 49 } 50 51 int main() 52 { 53 freopen("rocks.in","r",stdin); 54 freopen("rocks.out","w",stdout); 55 56 57 scanf("%d%d%d",&n,&T,&l); 58 59 for (int i=1; i<n; i++) 60 { 61 scanf("%d%d",&x,&a[i+1]); 62 add(x,i+1); 63 } 64 65 init(); 66 67 scanf("%d",&x); 68 scanf("%d",&a[x]); 69 70 int ans=0; 71 72 for (int k=1; k<=n; k++) 73 if ( (num[k]%2)==0 ) 74 ans^=(a[k]%(l+1)); 75 76 if (ans==0) printf("No\n"); 77 else printf("Yes\n"); 78 79 int tmp; 80 for (int i=2; i<=T; i++) 81 { 82 scanf("%d",&x); 83 scanf("%d",&tmp); 84 if ( (num[x]%2)==0 ) 85 { 86 ans^=(a[x]%(l+1)); 87 ans^=(tmp%(l+1)); 88 } 89 90 if (ans==0) printf("No\n"); 91 else printf("Yes\n"); 92 93 a[x]=tmp; 94 } 95 96 fclose(stdin); fclose(stdout); 97 return 0; 98 }
三道题的难度感觉算是中等的吧,唯一遗憾的是LCA的算法没有掌握好,要不然第二题也能拿到很好的成绩,但即便如此,第二题的最简单的O(N^2)还是没有去写,算是考试的失误了。