UPC2018组队训练赛第七场

题目来自ICPC 2017 Japan Tsukuba

 


 

A题:Secret of Chocolate Poles

有三种巧克力,分别是厚度为1的白色巧克力,厚度为1或者k的黑色巧克力。要求把巧克力放到高度为 l 的盒子里,并且要黑白相间,底部和顶部必须都是黑色的

当l=1,ans=1;当l<k,ans=(l-1)/2+1;当l=k,ans=(l-1)/2+2;当l>k时,就可以转化成排列组合问题了,枚举厚度为k的黑色巧克力数目i,然后对于每一种情况,再枚举厚度为1的黑色巧克力的数目j,那么此时排列的情况就是(i+j)! / ( i! * j! )。最后取和就行了。

因为阶乘会爆longlong,所以就用java写的

 1 import java.util.*;
 2 import java.math.BigInteger;
 3 public class Main {
 4  
 5     public static void main(String[] args) {
 6         // TODO Auto-generated method stub
 7         Scanner cin = new Scanner(System.in);
 8         BigInteger[]fac=new BigInteger[60];
 9         fac[0]=BigInteger.valueOf(1);
10         BigInteger tmp;
11         for(int i=1;i<60;i++) {
12             tmp=BigInteger.valueOf(i);
13             fac[i]=fac[i-1].multiply(tmp);
14         }
15         int l,k;
16         l= cin.nextInt();
17         k=cin.nextInt();
18         int flag=0;
19         long aa=0;
20         BigInteger ans=BigInteger.valueOf(0);
21         if(l==1)    aa=1;
22         else if(l<k) aa=(l-1)/2+1;
23         else if(l==k)   aa=(l-1)/2+2;
24         else
25         {
26             flag=1;
27             BigInteger tt,pp;
28             for(int i=0;i*(k+1)<=(l-1);i++)
29             {
30                 for(int j=0;j*2<=(l-1-i*(k+1));j++)
31                 {
32                     tt=fac[i].multiply(fac[j]);
33                     pp=fac[i+j].divide(tt);
34                     ans=ans.add(pp);
35                 }
36             }
37             for(int i=0;i*2<=(l-k);i++)
38             {
39                 for(int j=0;j*(k+1)<=(l-k-i*2);j++){
40                     tt=fac[i].multiply(fac[j]);
41                     pp=fac[i+j].divide(tt);
42                     ans=ans.add(pp);
43                 }
44             }
45         }
46         if(flag==1)
47             System.out.println(ans);
48         else
49         {
50             ans=BigInteger.valueOf(aa);
51             System.out.println(ans);
52         }
53              
54     }
55  
56 }
View Code

之后看了大佬的代码https://www.cnblogs.com/clrs97/p/8537178.html  发现可以用dp

f[i][j]代表高度为i,顶层颜色为j的方案数。(j=0,表示黑色,j=1表示白色)

 1 #include<cstdio>
 2 typedef __int128 lll;
 3 const int N=200;
 4 lll f[N][2],ans;//dark white
 5 int l,k,i;
 6 void write(lll x){
 7     if(x>=10)write(x/10);
 8     x%=10;
 9     printf("%d",(int)(x));
10 }
11 int main(){
12     scanf("%d%d",&l,&k);
13     f[1][0]++;
14     f[k][0]++;
15     for(i=1;i<=l;i++){
16         f[i+1][1]+=f[i][0];
17         f[i+1][0]+=f[i][1];
18         f[i+k][0]+=f[i][1];
19     }
20     for(i=1;i<=l;i++)ans+=f[i][0];
21     write(ans);
22 }
View Code

 

B题:Parallel lines

给偶数个点,两点形成直线,保证任意三点不在同一条直线,问最多能找到多少对平行线

写个搜索,找到所有的直线的可能情况,然后用vector存直线的两点,之后遍历找平行线。找平行线的话,可以用向量

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 struct node
 5 {
 6     int x,y;
 7 } Point[20];
 8 int n,ans=-1;
 9 bool vis[20];
10 vector<pair<int,int> >line;
11 void countt()
12 {
13     int tmp=0;
14     for(int i=0; i<line.size(); i++)
15     {
16         int x1=Point[line[i].first].x-Point[line[i].second].x;
17         int y1=Point[line[i].first].y-Point[line[i].second].y;
18         for(int j=i+1; j<line.size(); j++)
19         {
20             int x2=Point[line[j].first].x-Point[line[j].second].x;
21             int y2=Point[line[j].first].y-Point[line[j].second].y;
22             if(x1*y2==x2*y1)
23             {
24                 tmp++;
25             }
26         }
27     }
28     ans=max(ans,tmp);
29 }
30 void dfs(int now)
31 {
32     if(now==n+1)
33     {
34         countt();
35         return;
36     }
37     if(vis[now])
38     {
39         dfs(now+1);
40     }
41     else
42     {
43         for(int i=1; i<=n; i++)
44         {
45             if(vis[i]||i==now)
46             {
47                 continue;
48             }
49             line.push_back(make_pair(now,i));
50             vis[now]=vis[i]=1;
51             dfs(now+1);
52             line.pop_back();
53             vis[now]=vis[i]=0;
54         }
55     }
56 }
57 int main()
58 {
59     scanf("%d",&n);
60     for(int i=1; i<=n; i++)
61     {
62         scanf("%d %d",&Point[i].x,&Point[i].y);
63     }
64     dfs(1);
65     printf("%d\n",ans);
66     return 0;
67 }
68  
View Code

 

C题:Medical Checkup

有很多个窗口,有n个人,每个人去窗口办理业务的时间不同,问在t分钟时,每个人分别在哪个窗口

首先求一下每个人在第一个窗口待的时间,然后遍历每个人,如果t小于当前这个人在第一个窗口待的时间,直接输出1;否则,我们可以发现每个人在其他的窗口待的时间是相同的,如果当前这个人办理业务需要的时间小于他前一个人的,那么他在以后的每一个窗口所带的时间就是h[i]=h[i]+h[i-1]-h[i]=h[i-1],不小于的话就直接是他自己办理业务的时间h[i],对于每一个人,用 tt=t-sum[i] 表示这个人离开第一个窗口后还剩的时间,用 tt/h[i]+1,代表在tt这段时间里他能往后走多少个窗口,最后再加上第一个窗口(tt/h[i]+2)就是最终所在的窗口编号了。

 1  
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=100050;
 5 int n;
 6 ll h[N],sum[N],t;
 7 int main()
 8 {
 9     scanf("%d %lld",&n,&t);
10     for(int i=1;i<=n;i++)
11     {
12         scanf("%lld",&h[i]);
13         sum[i]=sum[i-1]+h[i];
14     }
15     for(int i=1;i<=n;i++)
16     {
17         ll tt=t-sum[i];
18         if(tt<0)
19         {
20             printf("1\n");
21             continue;
22         }
23         else
24         {
25             if(h[i]<h[i-1])
26             {
27                 h[i]+=(h[i-1]-h[i]);
28             }
29             ll ans=tt/h[i];
30             ans+=2;
31             printf("%lld\n",ans);
32         }
33     }
34     return 0;
35 }
View Code

 

G题:Rendezvous on a Tetrahedron

把三维展成二维,可以发现有循环节

把最终点的坐标转化到第一个循环节里,再讨论在哪个区域,然后再与输入的边匹配,得到最终的面的编号

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define PI acos(-1.0)
 4 struct node
 5 {
 6     double x,y;
 7 }p1,p2;
 8 double getpi(double x)
 9 {
10     return x*PI/180.0;
11 }
12 double fun(double x)
13 {
14     while(x>2)
15     {
16         x-=2;
17     }
18     return x;
19 }
20 int findArea(node p)
21 {
22     if(p.x+p.y-1<0||(p.x+p.y-3>0&&p.x<2&&p.y<2))
23         return 1;
24     else if((p.x+p.y-1>0&&p.x<1&&p.y<1)||(p.x+p.y-3<0&&p.x<2&&p.x>1&&p.y<2&&p.y>1))
25         return 2;
26     else if((p.x+p.y-2<0&&p.x>1&&p.x<2&&p.y<1)||(p.x+p.y-2>0&&p.x<1&&p.y>1&&p.y<2))
27         return 3;
28     else if((p.x+p.y-2<0&&p.x<1&&p.y>1&&p.y<2)||(p.x+p.y-2>0&&p.x>1&&p.x<2&&p.y<1))
29         return 4;
30 }
31 int findAns(char ch,int a)
32 {
33     if(ch=='B')
34     {
35         if(a==1)    return 1;
36         else if(a==2)   return 4;
37         else if(a==3)   return 3;
38         else if(a==4)   return 2;
39     }
40     else if(ch=='C')
41     {
42         if(a==1)    return 2;
43         else if(a==2)   return 4;
44         else if(a==3)   return 1;
45         else if(a==4)   return 3;
46     }
47     else if(ch=='D')
48     {
49         if(a==1)    return 3;
50         else if(a==2)   return 4;
51         else if(a==3)   return 2;
52         else if(a==4)   return 1;
53     }
54 }
55 int main()
56 {
57     char op1[3],op2[3];
58     int d1,l1,d2,l2;
59     scanf("%s%d%d",op1,&d1,&l1);
60     scanf("%s%d%d",op2,&d2,&l2);
61  
62     p1.x=l1*sin(getpi(60.0-d1*1.0))/sin(getpi(120.0));
63     p1.y=l1*sin(getpi(d1*1.0))/sin(getpi(120.0));
64  
65     p2.x=l2*sin(getpi(60.0-d2*1.0))/sin(getpi(120.0));
66     p2.y=l2*sin(getpi(d2*1.0))/sin(getpi(120.0));
67  
68     p1.x=fun(p1.x);
69     p1.y=fun(p1.y);
70  
71     p2.x=fun(p2.x);
72     p2.y=fun(p2.y);
73  
74     int a1=findArea(p1);
75     int a2=findArea(p2);
76  
77     int ans1=findAns(op1[0],a1);
78     int ans2=findAns(op2[0],a2);
79  
80     if(ans1==ans2)  printf("YES\n");
81     else            printf("NO\n");
82  
83     return 0;
84  
85 }
View Code

 

I题:Starting a Scenic Railroad Service

参考https://blog.csdn.net/xnmzdxws/article/details/80070867

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=2e5;
 4 int n,a[N+5],b[N+5],ans1,ans2,r[N+5],sn,sa[N+5],sb[N+5],sc[N+5];
 5 int main()
 6 {
 7     scanf("%d",&n);
 8     for(int i=1;i<=n;i++)
 9     {
10         scanf("%d%d",&a[i],&b[i]);
11         sa[a[i]]++;
12         sb[b[i]]++;
13         sc[a[i]]++;
14         sc[b[i]]--;
15         sn=max(sn,b[i]);
16     }
17     for(int i=1;i<=sn;i++)
18     {
19         sa[i]+=sa[i-1];
20         sb[i]+=sb[i-1];
21     }
22     for(int i=1;i<=n;i++)
23         ans1=max(ans1,sa[b[i]-1]-sb[a[i]]);
24     for(int i=1;i<=sn;i++)
25     {
26         sc[i]+=sc[i-1];
27         ans2=max(ans2,sc[i]);
28     }
29     printf("%d %d\n",ans1,ans2);
30     return 0;
31 }
View Code

 

posted @ 2018-08-29 18:59  Scott_Wong  阅读(176)  评论(0编辑  收藏  举报