Codeforces Round #279 (Div. 2)

A. Team Olympiad

水题英文还这么长。。。

 1 #include<bits/stdc++.h>
 2 #define eps 1e-9
 3 #define FOR(i,j,k) for(int i=j;i<=k;i++)
 4 using namespace std;
 5 typedef long long LL;
 6 int i,j,k,n,m,x,y,T,ans,big,cas;
 7 bool flag;
 8 vector <int> a[5];
 9 int num,t;
10 int main()
11 {
12     scanf("%d",&n);
13     for (i=1;i<=n;i++)
14     {
15         scanf("%d",&t);
16         a[t].push_back(i);
17     }
18     num=min((int)a[1].size(),(int)a[2].size());
19     num=min(num,(int)a[3].size());
20     printf("%d\n",num);
21     for (i=0;i<num;i++)
22     {
23         printf("%d %d %d\n",a[1][i],a[2][i],a[3][i]);
24     }
25     return 0;
26 }
View Code

B. Queue

有n个人排队,每个人都有一个编号,现给出每个人前边一人的编号和后边一人的编号(如果没有人则是0),求出原来队中人的顺序(输出编号)。

模拟,因为编号只有10^6,因此可以开两个10^6的数组,a[i][0]记录编号为i的人前边的前边的人的编号,a[i][1]记录编号为i的人后边的后边的人的编号。

显然从0开始能够确定偶数位置人的顺序,然后将他们标记为-1,再根据剩下的确定奇数位置的人的顺序即可。

 1 #include<bits/stdc++.h>
 2 #define eps 1e-9
 3 #define FOR(i,j,k) for(int i=j;i<=k;i++)
 4 using namespace std;
 5 typedef long long LL;
 6 int i,j,k,n,m,x,y,T,big,cas,a[1000006][2],st,l[200005],r[200005],ans[200005],temp;
 7 bool flag;
 8 int main()
 9 {
10     scanf("%d",&n);
11     for (i=1;i<=n;i++)
12     {
13         scanf("%d%d",&l[i],&r[i]);
14         a[r[i]][0]=l[i];
15         a[l[i]][1]=r[i];
16     }
17     for (st=a[0][1],j=2;st!=0;j+=2)//确定偶数位置人 
18     {
19         ans[j]=st;
20         temp=a[st][1];
21         a[st][0]=-1;//已经确定位置的人标记为-1 
22         a[st][1]=-1;
23         st=temp;
24     }
25     for (i=1;i<=n;i++) 
26         if (a[l[i]][0]==0) 
27         {
28             st=l[i];//找到奇数位置最前边的人 
29             break;
30         }
31     ans[1]=st;    
32     j=1;
33     for (;st!=0;st=a[st][1],j+=2)//确定奇数位置的人 
34     {
35         ans[j]=st;
36     }
37     for (i=1;i<n;i++) printf("%d ",ans[i]);
38     printf("%d\n",ans[n]);
39     return 0;
40 }
View Code

C. Hacking Cypher

给一个大数(长度10^6)问能够否分割成两个数,前边的能被a整除,后边的能被b整除,所有数不能有前导零。

模拟,取模的几个性质应该都懂吧,设某个数是def,那么def=d*100+e*10+f ,def mod n = ((d mod n)*(100 mod n)+(e mod n)*(10 mod n)+f mod n) mod n

设pre[i]为前i位能否整除a,suf[j]为后j为能否整除b。先预处理出pre和suf,显然pre[i]=true 并且 suf[i+1]=true的时候就是答案。

求suf的时候就可以通过前一位的pre值判断是否有解了,因此代码中没有开suf数组。

 1 #include<bits/stdc++.h>
 2 #define eps 1e-9
 3 #define FOR(i,j,k) for(int i=j;i<=k;i++)
 4 using namespace std;
 5 typedef long long LL;
 6 int i,j,k,n,m,x,y,T,ans,big,cas,a,b,len,w;
 7 bool flag,pre[1000005];
 8 char s[1000005];
 9 int main()
10 {
11     scanf("%s",s);
12     scanf("%d%d",&a,&b);
13     len=strlen(s);
14     for (i=0;i<len-1;i++)
15     {
16         x=(x*10+s[i]-'0')%a;
17         if (x==0)
18         {
19             pre[i]=true;
20         }
21     }
22     w=1;x=0;
23     for (i=len-1;i>0;i--)
24     {
25         x=(x+w*(s[i]-'0'))%b;
26         w=w*10%b;
27         if (x==0&&pre[i-1]&&s[i]!='0')
28         {
29             printf("YES\n");
30             for (j=0;j<i;j++)
31             {
32                 printf("%c",s[j]);
33             }
34             printf("\n");
35             for (j=i;j<len;j++)
36             {
37                 printf("%c",s[j]);
38             }
39             printf("\n");
40             return 0;
41         }
42     }
43     
44     printf("NO\n");
45     return 0;
46 }
View Code

D. Chocolate

给两个巧克力,尺寸分别为a1*b1,a2*b2,现在想让它们的面积相同,有两种措施:

1.吃掉其中一个巧克力的一半

2.吃掉其中一个巧克力的1/3

并且剩下每次操作后剩余巧克力尺寸是整数,问至少操作几次。。。并输出最终巧克力的尺寸

先让a1,a2,b1,b2分别不断整除2再不断整除3,直到不能整除为止,如果最终的a1*b1不等于a2*b2,则说明无解,输出-1

(假设存在有解a1,b1,a2,b2,则由题目一定有a1*b1=a2*b2,a1*b1,a2*b2一定有相同的2的因子数和3的因子数,这时让它们不断整除2整除3,直到不能整除为止,a1*b1=a2*b2仍然成立)

 

设s1=a1*b1,s2=a2*b2,则如果s1/gcd(s1,s2)不等于s2/gcd(s1,s2),说明无解。

有解的时候s1'=s2',一定有s1'/gcd(s1',s2')=s2'/gcd(s1',s2')=s1/gcd(s1,s2)=s2/gcd(s1,s2)

下面就是解这个式子:

s1*(1/2)x1*(2/3)y1 =s2*(1/2)x2*(2/3)y2 可以化简为

s1 =s2 * 2x1-x2-y1+y2 * 3y1-y2
找s1与s2关于2和3的因子数之差就能算出答案。

 1 #include<bits/stdc++.h>
 2 #define eps 1e-9
 3 #define FOR(i,j,k) for(int i=j;i<=k;i++)
 4 using namespace std;
 5 typedef long long LL;
 6 LL i,j,k,n,m,x,y,T,ans,big,cas,a[5],b[5],c[5],d[5],t,thr,two;
 7 bool flag;
 8 int main()
 9 {
10     for (i=1;i<=4;i++) scanf("%I64d",&a[i]);
11     for (i=1;i<=4;i++)
12     {
13         t=a[i];
14         while (t%2==0)
15         {
16             t/=2;
17             b[i]++;//记录因子2的个数 
18         }
19         while (t%3==0)
20         {
21             t/=3;
22             c[i]++;//记录因子3的个数 
23         }
24         d[i]=t;
25     }
26     if (d[1]*d[2]!=d[3]*d[4]) 
27     {
28         printf("-1\n");
29         return 0;
30     }
31     thr=c[3]+c[4]-c[1]-c[2];
32     if (thr>0)
33     {
34         t=thr;
35         while (t>0&&a[3]%3==0)
36         {
37             a[3]=a[3]*2/3;
38             t--;
39         }
40         while (t>0&&a[4]%3==0)
41         {
42             a[4]=a[4]*2/3;
43             t--;
44         }
45     } else
46     {
47         t=-thr;
48         while (t>0&&a[1]%3==0)
49         {
50             a[1]=a[1]*2/3;
51             t--;
52         }
53         while (t>0&&a[2]%3==0)
54         {
55             a[2]=a[2]*2/3;
56             t--;
57         }
58     }
59     two=b[3]+b[4]-b[1]-b[2]+thr;//记得加上因除去因子3而多出来的因子2 
60     
61     if (two>0)
62     {
63         t=two;
64         while (t>0&&a[3]%2==0)
65         {
66             a[3]=a[3]/2;
67             t--;
68         }
69         while (t>0&&a[4]%2==0)
70         {
71             a[4]=a[4]/2;
72             t--;
73         }
74     } else
75     {
76         t=-two;
77         while (t>0&&a[1]%2==0)
78         {
79             a[1]=a[1]/2;
80             t--;
81         }
82         while (t>0&&a[2]%2==0)
83         {
84             a[2]=a[2]/2;
85             t--;
86         }
87     }
88     printf("%I64d\n",abs(thr)+abs(two));
89      printf("%I64d %I64d\n%I64d %I64d\n",a[1],a[2],a[3],a[4]);
90     return 0;
91 }
View Code

E. Restoring Increasing Sequence

给出严格递增的几个数,其中几个数的某几位不知道用符号?给出,输出一种方案。

分类讨论,这类题目写的好烦=。=#

首先讨论与上一位的长度(第一个数的上一位设为0)的关系,如果他们的长度相等再从头到尾递归扫描。

用dfs(i)=0表示到第i位是否需要向前边借位,比如数据:

pre=14349

now=14?4?

now的第5位的问号处只能是0,这时如果要满足题意,就一定要求now的前边4位组成的数 比 pre的前四位组成的数大,因此dfs(5)=1。

如果到递归第一个问号后仍然需要借位,则说明无解,比如:

pre=14949

now=14?49

第一个问号处dfs(3)=1,而前边两位的数不可能比pre的前两位大,因此输出NO。

其它的讨论细节乱搞一下,再乱搞乱搞。。。。还是详见代码吧:

  1 #include<bits/stdc++.h>
  2 #define eps 1e-9
  3 #define FOR(i,j,k) for(int i=j;i<=k;i++)
  4 using namespace std;
  5 typedef long long LL;
  6 int i,j,k,n,m,x,y,T,big,cas,last_len,len;
  7 bool flag;
  8 char last[10],s[10],bf[10],ans[100005][10];
  9 bool dfs(int x)//false为不需要进位,true表示需要进位 
 10 {
 11     if (x>=len) return 1; 
 12     if (s[x]=='?')
 13     {
 14         if (dfs(x+1))
 15         {
 16             s[x]=last[x];
 17             if (last[x]=='9')
 18             {
 19                 s[x]='0';
 20                 return 1;
 21             }else
 22             {
 23                 s[x]=last[x]+1;
 24                 return 0;
 25             }
 26         }else
 27         {
 28             s[x]=last[x];
 29             return 0;
 30         }
 31     }else
 32     {
 33         if (s[x]>last[x])
 34         {
 35             for (int i=x+1;i<len;i++)
 36             {
 37                 if (bf[i]=='?') s[i]='0';
 38             }
 39             return 0;
 40         }else
 41         if (s[x]<last[x])
 42         {
 43             for (int i=x+1;i<len;i++)
 44             {
 45                 if (bf[i]=='?') s[i]='0';
 46             }
 47             return 1;
 48         }else
 49         {
 50             return dfs(x+1);
 51         }
 52     }
 53 }
 54             
 55 
 56 int main()
 57 {
 58     scanf("%d",&n);
 59     strcpy(last,"0"); last_len=0;
 60     for (i=1;i<=n;i++)
 61     {
 62         scanf("%s",s);
 63         len=strlen(s);
 64         if (last_len>len)
 65         {
 66             printf("NO\n");
 67             return 0;
 68         }else
 69         if (last_len<len)
 70         {
 71             if (s[0]=='?') s[0]='1';
 72             for (j=1;j<len;j++)
 73             {
 74                 if (s[j]=='?')
 75                 {
 76                     s[j]='0';
 77                 }
 78             }
 79             strcpy(ans[i],s);
 80             last_len=len;
 81             strcpy(last,s);
 82         }else
 83         {
 84             strcpy(bf,s);
 85             if (dfs(0))
 86             {
 87                 printf("NO\n");
 88                 return 0;
 89             }else
 90             {
 91                 strcpy(ans[i],s);
 92                 last_len=len;
 93                 strcpy(last,s);
 94             }
 95         }
 96     }
 97     printf("YES\n");
 98     for (i=1;i<=n;i++)
 99     {
100         printf("%s\n",ans[i]);
101     }
102     return 0;
103 }
View Code

F. Treeland Tour

给一棵最多6000个结点的树,每个点有权值,求其中的一条链,使得LIS的序列和最大。

网上有人竟然枚举起点+求LIS o(N^2logN) 通过了,醉了,看来数据是很水了,在board上点开看了几个人的代码也是这样写的,不知道正解是怎样


啊,第一场做出5道题的CF比赛,第一次排名这么靠前,只是不算rating。。。截个图

 

posted @ 2014-11-24 11:57  zhyfzy  阅读(487)  评论(0编辑  收藏  举报