zoukankan      html  css  js  c++  java
  • 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
    ",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
    ");
    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
    ",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
    ");
    81     else            printf("NO
    ");
    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
    ",ans1,ans2);
    30     return 0;
    31 }
    View Code

    如有错误,请指正,感谢!
  • 相关阅读:
    react获取ref的几种形式
    vue与react的小区别
    vue当中计算属性重新计算依赖关系
    移动端常见问题
    WX小程序--开发中相关问题记录
    ECMAScript6 入门 Set 和Map结构
    ECMAScript6 入门 Class 的基本语法与继承
    ECMAScript6 入门 Generator
    ECMAScript6 入门 Promise
    ECMAScript6 入门 Symbol
  • 原文地址:https://www.cnblogs.com/scott527407973/p/9556301.html
Copyright © 2011-2022 走看看