【日记】6.12

  刚到省实验的第一次考试,大家水平都相差不多,也基本没有分出什么名次。

  这回考试的题目第一个有一点水,是USACO 2.2.4,也算是技巧性的题目了,具体的不再多说,可以看nocow上的解析。

Usaco 2.2.4
  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函数来把他转化为一个很常见的取数游戏模型。

rocks and trees
 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)还是没有去写,算是考试的失误了。

posted @ 2012-06-13 07:35  守護N1身边  阅读(137)  评论(0编辑  收藏  举报